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?

Réponses:


218

Votre premier exemple est effectivement ce dont vous avez besoin:

<TextBlock Text="{Binding CelsiusTemp, StringFormat={}{0}°C}" />

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>

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


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;
            }
        }

19
Cela va à l'encontre du point de vue de la séparation View-Viewmodel
Askolein
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.