Use StringFormat para agregar una cadena a un enlace WPF XAML

124

Tengo una aplicación WPF 4 que contiene un TextBlock que tiene un enlace unidireccional a un valor entero (en este caso, una temperatura en grados Celsius). El XAML se ve así:

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

Esto funciona bien para mostrar el valor de temperatura real, pero me gustaría formatear este valor para que incluya ° C en lugar de solo el número (30 ° C en lugar de solo 30). He estado leyendo sobre StringFormat y he visto varios ejemplos genéricos como este:

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

y

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

Desafortunadamente, ninguno de los ejemplos que he visto ha agregado una cadena al valor enlazado como estoy tratando de hacer. Estoy seguro de que debe ser algo simple, pero no tengo suerte de encontrarlo. ¿Alguien puede explicarme cómo hacer eso?

bmt22033
fuente

Respuestas:

217

Su primer ejemplo es efectivamente lo que necesita:

<TextBlock Text="{Binding CelsiusTemp, StringFormat={}{0}°C}" />
Reed Copsey
fuente
20
¿Por qué el formato de cadena en xaml tiene el inicio vacío {}?
Jonesopolis
66
@Jonesopolis Está en los documentos, pero si la cadena de formato comienza con a {, proporciona un mecanismo para escapar, ya que {}ya tiene significado en xaml.
Reed Copsey
55
No veo dónde la documentación explica los principales {}.
Eric
55
@Eric Al igual que mucha documentación, apesta: la muestran, pero no explican.
Reed Copsey
19
aquí la documentación del misterioso {}: msdn.microsoft.com/en-us/library/ms744986.aspx
Jotrius
106

Aquí hay una alternativa que funciona bien para la legibilidad si tiene el enlace en el medio de la cadena o enlaces múltiples:

<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
fuente
66
Me gusta esta respuesta un poco mejor porque puedo insertar texto de una biblioteca de cadenas fácilmente. Por supuesto, si realmente le preocupa la internacionalización, probablemente sea mejor usar un convertidor para que el orden del número y las unidades no sea fijo. <Run Text = "{x: Static s: UIStrings.General_FahrenheitAbbreviation}" />
Matt Becker
1
Esta es una gran solución, pero obtengo espacios adicionales en la pantalla de texto final, entre las ejecuciones de texto, ¿alguna idea de por qué? En su ejemplo veo0 °C ( 32 °F)
Conrad
No es súper útil si desea hacer un formato de cadena real (es decir, controlar el número de lugares decimales, etc.).
BrainSlugs83
55
@Conrad Si no desea los espacios entre cada ejecución, debe colocar esas ejecuciones en una sola línea de la siguiente manera: <TextBlock> <Run Text = "{Binding CelsiusTemp}" /> <Run Text = "° C" / > <Run Text = "(" /: <Run Text = "{Binding Fahrenheit}" /> <Run Text = "° F)" /> </TextBlock>
Ladislav Ondris
92

Tenga en cuenta que el uso de StringFormat en enlaces solo parece funcionar para propiedades de "texto". Usar esto para Label.Content no funcionará

Casper Ehrenborg
fuente
15
Un punto MUY importante que me llevó a intentarlo hasta que me desesperé y encontré este comentario para validar mi sospecha.
DonBoitnott
64
ContentStringFormatviene al rescate, ejemplo: Content="{Binding Path=TargetProjects.Count}" ContentStringFormat="Projects: {0}".
astrowalker
2
Gracias Casper, verdadero héroe por publicar esa información.
DaWiseguy
55
para encabezados GridViewColumn, useHeaderStringFormat="{}{0} For Report"
Felix
2
Si está utilizando datos de tiempo de diseño, parece que necesita reconstruir el proyecto después de editar ContentStringFormat para que los cambios se reflejen en el diseñador, mientras que StringFormat, como se usa en un cuadro de texto, actualizará el diseñador en tiempo real.
Richard Moore
-8

En xaml

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

De ViewModelesta manera, establecer el valor también funciona:

 public string CelsiusTemp
        {
            get { return string.Format("{0}°C", _CelsiusTemp); }
            set
            {
                value = value.Replace("°C", "");
              _CelsiusTemp = value;
            }
        }
Rajesh Nath
fuente
19
Esto va en contra del punto de separación de View-Viewmodel
Askolein