Użyj StringFormat, aby dodać ciąg do powiązania WPF XAML

125

Mam aplikację WPF 4, która zawiera TextBlock, który ma jednokierunkowe powiązanie z wartością całkowitą (w tym przypadku jest to temperatura w stopniach Celsjusza). XAML wygląda następująco:

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

Działa to dobrze do wyświetlania rzeczywistej wartości temperatury, ale chciałbym sformatować tę wartość, aby zawierała ° C zamiast tylko liczby (30 ° C zamiast tylko 30). Czytałem o StringFormat i widziałem kilka ogólnych przykładów, takich jak ten:

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

i

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

Niestety, żaden z przykładów, które widziałem, nie dołączał ciągu do wartości związanej, tak jak próbuję to zrobić. Jestem pewien, że to musi być coś prostego, ale nie mam szczęścia, aby to znaleźć. Czy ktoś może mi wyjaśnić, jak to zrobić?

bmt22033
źródło

Odpowiedzi:

218

Twój pierwszy przykład jest tym, czego potrzebujesz:

<TextBlock Text="{Binding CelsiusTemp, StringFormat={}{0}°C}" />
Reed Copsey
źródło
20
Dlaczego format ciągu w xaml ma początkowy pusty {}?
Jonesopolis
6
@Jonesopolis Jest w dokumentacji - ale jeśli ciąg formatu zaczyna się od a {, zapewnia mechanizm ucieczki, ponieważ {}ma już znaczenie w xaml.
Reed Copsey
5
Nie widzę, gdzie dokumentacja wyjaśnia wiodący {}.
Eric
5
@Eric Jak większość dokumentacji, śmierdzi - demonstrują to, ale nie wyjaśniają.
Reed Copsey
19
tutaj dokumentacja tajemniczego {}: msdn.microsoft.com/en-us/library/ms744986.aspx
Jotrius
107

Oto alternatywa, która działa dobrze dla czytelności, jeśli masz Binding w środku ciągu lub wiele powiązań:

<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
źródło
6
Ta odpowiedź podoba mi się trochę lepiej, ponieważ mogę łatwo wstawić tekst z biblioteki ciągów. Oczywiście, jeśli naprawdę martwisz się internacjonalizacją, prawdopodobnie lepiej byłoby użyć konwertera, aby kolejność liczby i jednostek nie była ustalona. <Run Text = "{x: Static s: UIStrings.General_FahrenheitAbbreviation}" />
Matt Becker
1
To świetne rozwiązanie, ale otrzymuję dodatkowe spacje w końcowym wyświetlaniu tekstu, między przebiegami tekstu - czy wiesz, dlaczego? W twoim przykładzie widzę0 °C ( 32 °F)
Conrad
Nie jest to bardzo przydatne, jeśli chcesz wykonać faktyczne formatowanie ciągów (tj. Kontrolować liczbę miejsc dziesiętnych itp.).
BrainSlugs83
5
@Conrad Jeśli nie chcesz spacji między każdym uruchomieniem, powinieneś umieścić je w jednym wierszu w następujący sposób: <TextBlock> <Run Text = "{Binding CelsiusTemp}" /> <Run Text = "° C" / > <Run Text = "(" /: <Run Text = "{Binding Fahrenheit}" /> <Run Text = "° F)" /> </TextBlock>
Ladislav Ondris
94

Zauważ, że użycie StringFormat w Bindings wydaje się działać tylko dla właściwości „text”. Używanie tego dla Label.Content nie będzie działać

Casper Ehrenborg
źródło
16
Bardzo ważny punkt, który wziął mnie próbuje go aż mam zdesperowany i znaleźć ten komentarz zweryfikować podejrzenia.
DonBoitnott
64
ContentStringFormatprzychodzi na ratunek, np Content="{Binding Path=TargetProjects.Count}" ContentStringFormat="Projects: {0}".
astrowalker
2
Dzięki Casperowi, prawdziwemu bohaterowi za opublikowanie tych informacji.
DaWiseguy
5
dla nagłówków GridViewColumn użyjHeaderStringFormat="{}{0} For Report"
Felix,
2
Jeśli używasz danych czasu projektowania, wydaje się, że musisz przebudować projekt po edycji ContentStringFormat, aby uzyskać zmiany do odzwierciedlenia w projektancie, podczas gdy StringFormat, jak jest używany w, powiedzmy, pole tekstowe zaktualizuje projektanta w czasie rzeczywistym.
Richard Moore
-8

W XAML

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

W ViewModelten sposób ustawienie wartości działa również:

 public string CelsiusTemp
        {
            get { return string.Format("{0}°C", _CelsiusTemp); }
            set
            {
                value = value.Replace("°C", "");
              _CelsiusTemp = value;
            }
        }
Rajesh Nath
źródło
19
Jest to sprzeczne z całym punktem oddzielenia modelu View-View
Askolein