165

I have a WPF 4 application that contains a TextBlock which has a one-way binding to an integer value (in this case, a temperature in degrees Celsius). The XAML looks like this:

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

This works fine for displaying the actual temperature value but I'd like to format this value so it includes °C instead of just the number (30°C instead of just 30). I've been reading about StringFormat and I've seen several generic examples like this:

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

and

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

Unfortunately, none of the examples I've seen have appended a string to the bound value as I'm trying to do. I'm sure it's got to be something simple but I'm not having any luck finding it. Can anyone explain to me how to do that?

4 Answers 4

316

Your first example is effectively what you need:

<TextBlock Text="{Binding CelsiusTemp, StringFormat={}{0}°C}" />
Sign up to request clarification or add additional context in comments.

14 Comments

Why does the string format in xaml have the leading empty {}?
@Jonesopolis It's in the docs - but if your format string starts with a {, it provides a mechanism to escape, since {} already has meaning in xaml.
I do not see where the documentation explains the leading {}.
@Eric Like much documentation, it stinks - they demo it, but don't explain.
here the documentation of the mysterious {}: msdn.microsoft.com/en-us/library/ms744986.aspx
|
156

Please note that using StringFormat property in Bindings only seems to work for "text" properties. Using this for Label.Content will not work

9 Comments

A VERY important point that took me trying it until I got desperate and found this comment to validate my suspicion.
ContentStringFormat comes to the rescue, example: Content="{Binding Path=TargetProjects.Count}" ContentStringFormat="Projects: {0}".
for GridViewColumn headers, use HeaderStringFormat="{}{0} For Report"
If you're using design time data it seems you need to rebuild the project after editing ContentStringFormat to get changes to reflect in the designer, whereas StringFormat as used on say a text box will update the designer in realtime.
This heroic answer has made it possible to waste less than ~5 minutes before understanding what was going wrong with this. Casper and @astrowalker, you are still saving people's time, year after year! Kudos!
|
143

Here's an alternative that works well for readability if you have the Binding in the middle of the string or multiple bindings:

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

5 Comments

I like this answer a little better because I can insert text from a string library easily. Of course if you're really worried about internationalization, you'd probably be better off using a converter so the order of the number and units isn't fixed. <Run Text="{x:Static s:UIStrings.General_FahrenheitAbbreviation}" />
This is a great solution, but I am getting extra spaces in the final text display, between the Text Runs - any idea why? In your example I see 0 °C ( 32 °F)
It's not super useful if you want to do actual string formatting (i.e. control the number of decimal places, etc.).
@Conrad If you don't want the spaces between each run, you should put those runs on a single line as follows: <TextBlock> <Run Text="{Binding CelsiusTemp}"/><Run Text="°C"/><Run Text=" ("/:<Run Text="{Binding Fahrenheit}"/><Run Text="°F)"/> </TextBlock>
@BrainSlugs83 That's what you'd use a ValueConverter for, I think
-19

In xaml

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

In ViewModel, this way setting the value also works:

 public string CelsiusTemp
        {
            get { return string.Format("{0}°C", _CelsiusTemp); }
            set
            {
                value = value.Replace("°C", "");
              _CelsiusTemp = value;
            }
        }

4 Comments

This goes against the whole point of View-Viewmodel separation
Sometimes a "hack" is the way to go, why not?
This does not have to be always "hack". It is OK to provide formatted text in ViewModel and display it in several places in View (View is then less bulky). And the role of ViewModel is to separate View from Model in MVVM, isn't it?
How to represent the data depends on the View, not the ViewModel. Moreover, the setter that replaces text looks awful - the dirtiest hack I've ever seen.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.