Utilisez StringFormat pour ajouter une chaîne à une liaison WPF XAML

125

J'ai une application WPF 4 qui contient un TextBlock qui a une liaison unidirectionnelle à une valeur entière (dans ce cas, une température en degrés Celsius). Le XAML ressemble à ceci:

<TextBlock x:Name="textBlockTemperature">
        <Run Text="{Binding CelsiusTemp, Mode=OneWay}"/></TextBlock>

Cela fonctionne très bien pour afficher la valeur de température réelle, mais j'aimerais formater cette valeur afin qu'elle inclue ° C au lieu du nombre (30 ° C au lieu de seulement 30). J'ai lu sur StringFormat et j'ai vu plusieurs exemples génériques comme celui-ci:

// format the bound value as a currency
<TextBlock Text="{Binding Amount, StringFormat={}{0:C}}" />

et

// preface the bound value with a string and format it as a currency
<TextBlock Text="{Binding Amount, StringFormat=Amount: {0:C}}"/>

Malheureusement, aucun des exemples que j'ai vus n'a ajouté une chaîne à la valeur liée comme j'essaie de le faire. Je suis sûr que ça doit être quelque chose de simple mais je n'ai pas de chance de le trouver. Quelqu'un peut-il m'expliquer comment faire cela?

bmt22033
la source

Réponses:

218

Votre premier exemple est effectivement ce dont vous avez besoin:

<TextBlock Text="{Binding CelsiusTemp, StringFormat={}{0}°C}" />
Reed Copsey
la source
20
Pourquoi le format de chaîne en xaml a-t-il le premier vide {}?
Jonesopolis
6
@Jonesopolis C'est dans la documentation - mais si votre chaîne de format commence par a {, elle fournit un mécanisme pour s'échapper, car elle a {}déjà un sens en xaml.
Reed Copsey
5
Je ne vois pas où la documentation explique le début {}.
Eric
5
@Eric Comme beaucoup de documentation, ça pue - ils en font la démonstration, mais n'expliquent pas.
Reed Copsey
19
voici la documentation du mystérieux {}: msdn.microsoft.com/en-us/library/ms744986.aspx
Jotrius
107

Voici une alternative qui fonctionne bien pour la lisibilité si vous avez la liaison au milieu de la chaîne ou plusieurs liaisons:

<TextBlock>
  <Run Text="Temperature is "/>
  <Run Text="{Binding CelsiusTemp}"/>
  <Run Text="°C"/>  
</TextBlock>

<!-- displays: 0°C (32°F)-->
<TextBlock>
  <Run Text="{Binding CelsiusTemp}"/>
  <Run Text="°C"/>
  <Run Text=" ("/>
  <Run Text="{Binding Fahrenheit}"/>
  <Run Text="°F)"/>
</TextBlock>
denis morozov
la source
6
J'aime un peu mieux cette réponse car je peux facilement insérer du texte à partir d'une bibliothèque de chaînes. Bien sûr, si vous êtes vraiment préoccupé par l'internationalisation, vous feriez probablement mieux d'utiliser un convertisseur afin que l'ordre du nombre et des unités ne soit pas fixe. <Run Text = "{x: Static s: UIStrings.General_FahrenheitAbbreviation}" />
Matt Becker
1
C'est une excellente solution, mais j'obtiens des espaces supplémentaires dans l'affichage final du texte, entre les passages de texte - une idée pourquoi? Dans votre exemple, je vois0 °C ( 32 °F)
Conrad
Ce n'est pas très utile si vous voulez faire un formatage de chaîne réel (c'est-à-dire contrôler le nombre de décimales, etc.).
BrainSlugs83
5
@Conrad Si vous ne voulez pas d'espaces entre chaque exécution, vous devez mettre ces exécutions sur une seule ligne comme suit: <TextBlock> <Run Text = "{Binding CelsiusTemp}" /> <Run Text = "° C" / > <Run Text = "(" /: <Run Text = "{Binding Fahrenheit}" /> <Run Text = "° F)" /> </TextBlock>
Ladislav Ondris
94

Veuillez noter que l'utilisation de StringFormat dans les liaisons ne semble fonctionner que pour les propriétés "texte". Utiliser ceci pour Label.Content ne fonctionnera pas

Casper Ehrenborg
la source
16
Un point TRÈS important qui m'a amené à l'essayer jusqu'à ce que je sois désespéré et que je trouve ce commentaire pour valider mes soupçons.
DonBoitnott
64
ContentStringFormatvient à la rescousse, par exemple: Content="{Binding Path=TargetProjects.Count}" ContentStringFormat="Projects: {0}".
astrowalker
2
Merci Casper, véritable héros pour avoir publié cette information.
DaWiseguy
5
pour les en-têtes GridViewColumn, utilisezHeaderStringFormat="{}{0} For Report"
Felix
2
Si vous utilisez des données au moment du design, il semble que vous deviez reconstruire le projet après avoir modifié ContentStringFormat pour que les modifications soient reflétées dans le concepteur, alors que StringFormat, tel qu'utilisé dans une zone de texte, mettra à jour le concepteur en temps réel.
Richard Moore
-8

En xaml

<TextBlock Text="{Binding CelsiusTemp}" />

Dans ViewModel, de cette façon, la définition de la valeur fonctionne également:

 public string CelsiusTemp
        {
            get { return string.Format("{0}°C", _CelsiusTemp); }
            set
            {
                value = value.Replace("°C", "");
              _CelsiusTemp = value;
            }
        }
Rajesh Nath
la source
19
Cela va à l'encontre du point de vue de la séparation View-Viewmodel
Askolein