154

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?

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
bmt22033
  • 6,880
  • 14
  • 69
  • 98

4 Answers4

296

Your first example is effectively what you need:

<TextBlock Text="{Binding CelsiusTemp, StringFormat={}{0}°C}" />
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 27
    Why does the string format in xaml have the leading empty `{}`? – Jonesopolis Apr 20 '16 at 19:33
  • 8
    @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. – Reed Copsey Apr 20 '16 at 19:34
  • could you link to the docs for xaml string formatting. I cannot find them. – Eric May 31 '16 at 17:28
  • 3
    @Eric https://msdn.microsoft.com/en-us/library/system.windows.data.bindingbase.stringformat%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396 – Reed Copsey May 31 '16 at 17:56
  • 5
    I do not see where the documentation explains the leading {}. – Eric May 31 '16 at 18:01
  • 5
    @Eric Like much documentation, it stinks - they demo it, but don't explain. – Reed Copsey May 31 '16 at 18:01
  • oh well, I had seen that page before and was hoping you knew of something better. – Eric May 31 '16 at 18:04
  • Trying to do this in XAML in a Windows 10 Universal app, and it complains that there is no `StringFormat` property. – BrainSlugs83 Sep 09 '16 at 00:13
  • @BrainSlugs83 This answer was for WPF (as tagged in the question), not UWP. – Reed Copsey Sep 09 '16 at 00:14
  • @ReedCopsey XAML was tagged in the question (which is the root technology at play here) and is not technically specific to WPF or UWP. -- Databinding is a core feature of XAML (core features are supposed to work the same even when using it just for plain-jane object graphs, and neither UWP or WPF is involved, etc.) -- anyway, I wasn't complaining, just calling it out as a caveat for others who may be in the same boat. – BrainSlugs83 Sep 13 '16 at 02:06
  • 30
    here the documentation of the mysterious {}: https://msdn.microsoft.com/en-us/library/ms744986.aspx – Jotrius Nov 03 '16 at 13:48
  • There is a StringFormat property in Xamarin Forms – Nick Turner Mar 08 '19 at 16:27
  • So this comes up as a top hit while I am searching for Xamarin info. At least in that flavor of XAML you can do (note the single quotes) – KnarfaLingus Sep 10 '19 at 01:13
  • 1
    you just need {} when the format string starts with the parameter {0}, it is not needed if the format string starts with a text. ex: "{}{0} + {1}" "Page {0} of {1}". Credit to [Dakianth](https://stackoverflow.com/users/1456496/dakianth) – TMoore Jan 14 '21 at 03:51
137

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>
denis morozov
  • 6,236
  • 3
  • 30
  • 45
  • 6
    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. – Matt Becker Nov 10 '15 at 15:19
  • 3
    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)`` – Conrad Aug 30 '16 at 13:47
  • It's not super useful if you want to do actual string formatting (i.e. control the number of decimal places, etc.). – BrainSlugs83 Sep 09 '16 at 00:12
  • 10
    @Conrad If you don't want the spaces between each run, you should put those runs on a single line as follows: – Ladislav Ondris Aug 15 '17 at 06:22
  • @BrainSlugs83 That's what you'd use a ValueConverter for, I think – Clonkex Feb 03 '22 at 04:53
137

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

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Casper Ehrenborg
  • 1,379
  • 1
  • 8
  • 2
  • 28
    A **VERY** important point that took me trying it until I got desperate and found this comment to validate my suspicion. – DonBoitnott Apr 27 '17 at 13:24
  • 95
    `ContentStringFormat` comes to the rescue, example: `Content="{Binding Path=TargetProjects.Count}" ContentStringFormat="Projects: {0}"`. – astrowalker Jun 05 '17 at 06:53
  • 2
    Thanks Casper, real hero for posting that info. – DaWiseguy May 02 '18 at 21:11
  • 5
    for GridViewColumn headers, use `HeaderStringFormat="{}{0} For Report"` – Felix Jul 03 '18 at 10:09
  • 2
    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. – Richard Moore Oct 29 '18 at 20:37
  • For Image's Source see [this question](https://stackoverflow.com/q/15580855/6131611) – Pavel Nov 26 '18 at 19:51
  • 1
    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! – Vector Sigma Oct 15 '19 at 00:24
  • 1
    And people keep asking why I love WPF so much. – alekstrust Jan 20 '20 at 21:52
  • For databinding Header property of `System.Windows.Controls.GroupBox` also use `HeaderStringFormat` – Adam Apr 21 '20 at 14:10
  • You can override the headers and components of controls like GroupBox that use Label to use TextBlock instead. That way you can still use StringFormat. – kenjara Sep 15 '20 at 15:47
-17

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;
            }
        }
チーズパン
  • 2,752
  • 8
  • 42
  • 63
Rajesh Nath
  • 39
  • 1
  • 5
  • 27
    This goes against the whole point of View-Viewmodel separation – Askolein May 31 '17 at 12:24
  • 1
    Sometimes a "hack" is the way to go, why not? – marsh-wiggle May 02 '21 at 17:13
  • 2
    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? – xMaa Jul 02 '21 at 18:38
  • 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. – Rustem Zinnatullin Sep 06 '22 at 07:12