Use StringFormat para adicionar uma sequência a uma ligação WPF XAML

124

Eu tenho um aplicativo WPF 4 que contém um TextBlock que tem uma ligação unidirecional a um valor inteiro (nesse caso, uma temperatura em graus Celsius). O XAML fica assim:

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

Isso funciona bem para exibir o valor real da temperatura, mas eu gostaria de formatar esse valor para incluir ° C em vez de apenas o número (30 ° C em vez de apenas 30). Eu tenho lido sobre StringFormat e vi vários exemplos genéricos como este:

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

e

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

Infelizmente, nenhum dos exemplos que eu vi anexou uma string ao valor associado, como estou tentando fazer. Tenho certeza de que deve ser algo simples, mas não estou tendo sorte em encontrá-lo. Alguém pode me explicar como fazer isso?

bmt22033
fonte

Respostas:

217

Seu primeiro exemplo é efetivamente o que você precisa:

<TextBlock Text="{Binding CelsiusTemp, StringFormat={}{0}°C}" />
Reed Copsey
fonte
20
Por que o formato de string no xaml tem o primeiro vazio {}?
Jonesopolis
6
@ Jonesopolis Está na documentação - mas se a sua sequência de formato começar com a {, ela fornece um mecanismo para escapar, já que {}já tem significado no xaml.
Reed Copsey
5
Não vejo onde a documentação explica os principais {}.
Eric
5
@ Eric Como muita documentação, ele fede - eles demonstram, mas não explicam.
Reed Copsey
19
aqui a documentação do misterioso {}: msdn.microsoft.com/en-us/library/ms744986.aspx
Jotrius
106

Aqui está uma alternativa que funciona bem para facilitar a leitura, se você tiver o Binding no meio da string ou várias ligações:

<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
fonte
6
Eu gosto desta resposta um pouco melhor porque posso inserir texto de uma biblioteca de strings facilmente. É claro que se você estiver realmente preocupado com a internacionalização, provavelmente seria melhor usar um conversor para que a ordem do número e das unidades não seja fixa. <Run Text = "{x: Static s: UIStrings.General_FahrenheitAbbreviation}" />
Matt Becker
1
Essa é uma ótima solução, mas estou obtendo espaços extras na exibição final do texto, entre as execuções de texto - alguma idéia do porquê? No seu exemplo eu vejo0 °C ( 32 °F)
Conrad
Não é super útil se você deseja formatar a string real (por exemplo, controlar o número de casas decimais, etc.).
BrainSlugs83
5
@Conrad Se você não quiser os espaços entre cada execução, coloque-as em uma única linha da seguinte maneira: <TextBlock> <Run Text = "{Binding CelsiusTemp}" /> <Run Text = "° C" / > <Executar Texto = "(" /: <Executar Texto = "{Vinculando Fahrenheit}" /> <Executar Texto = "° F)" /> </TextBlock>
Ladislav Ondris
92

Observe que o uso de StringFormat em Bindings parece funcionar apenas para propriedades de "texto". Usar isso para Label.Content não funcionará

Casper Ehrenborg
fonte
15
Um ponto MUITO importante que me levou a tentar até ficar desesperado e achei esse comentário para validar minha suspeita.
precisa saber é o seguinte
64
ContentStringFormatvem para o resgate, exemplo: Content="{Binding Path=TargetProjects.Count}" ContentStringFormat="Projects: {0}".
astrowalker
2
Obrigado Casper, verdadeiro herói por postar essa informação.
DaWiseguy
5
para cabeçalhos GridViewColumn, useHeaderStringFormat="{}{0} For Report"
Felix
2
Se você estiver usando dados de tempo de design, parece que precisa reconstruir o projeto após editar o ContentStringFormat para que as alterações sejam refletidas no designer, enquanto StringFormat, conforme usado em uma caixa de texto, atualizará o designer em tempo real.
Richard Moore
-8

No xaml

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

Em ViewModel, este definindo o valor de maneira também funciona:

 public string CelsiusTemp
        {
            get { return string.Format("{0}°C", _CelsiusTemp); }
            set
            {
                value = value.Replace("°C", "");
              _CelsiusTemp = value;
            }
        }
Rajesh Nath
fonte
19
Isso vai contra toda a ponto de separação View-ViewModel
Askolein