Trying out Binding.StringFormat


StringFormat is a new property in .Net 3.5 SP1, which is currently in Beta.  See Scott’s blog for more info on the beta.



When you bind data into a property on an element, it’s automatically type converted for you.  For example, this markup:


<StackPanel xmlns:sys=”clr-namespace:System;assembly=mscorlib”>





    <TextBlock Text=”{Binding}” /> <!– Simply bind to the DataContext –>




… shows a TextBlock with the text “123”.


If you want to have more control over the conversion of the value during binding, you can write a value converter for it.  For example, with this code:


public class TestConverter : IValueConverter



    public object Convert(object value, Type targetType, object parameter,

                          System.Globalization.CultureInfo culture)


        return String.Format(culture, “Cost: {0:C}”, value);



    public object ConvertBack(object value, Type targetType, object parameter,

                          System.Globalization.CultureInfo culture)


        throw new NotImplementedException();





… and this markup:


<StackPanel xmlns:sys=”clr-namespace:System;assembly=mscorlib”>


        <local:TestConverter x:Key=”testConverter” />






    <TextBlock Text=”{Binding Converter={StaticResource testConverter}}” />




… my TextBlock shows “Cost: $123.00”.



The New StringFormat Property


That’s great, but it’s too bad that you have to write a value converter to get that.  To make it simpler, we’ve added the StringFormat property to Binding, which causes the value to be run through, not surprisingly, the String.Format method.


So, the above can now be accomplished with this markup, and no code:


<StackPanel xmlns:sys=”clr-namespace:System;assembly=mscorlib”>





    <TextBlock Text=”{Binding StringFormat=Cost: {0:C}}” />





If you just want to add the format specifier, e.g. just “{0:C}” rather than “Cost: {0:C}”, there’s nothing unusual if you’re in code, but in Xaml the syntax gets confused with the markup extension syntax.  That is, a property value that starts with a “{“ (as the first character) is interpreted to be a markup extension, such as {Binding}, {DynamicResource}, {x:Null}, etc.  The way to really have a “{“ as the first character of a property value is to escape it with a “{}”, so the above example becomes:


<TextBlock Text=”{Binding StringFormat={}{0:C}}” />    



Not Just on Bindings


StringFormat shows up on some controls too.  For example, just like ContentControl (the base class of Button) lets you template your content with the ContentTemplate property, you can now format your content with the ContentFormatString property, such as:


<Button ContentStringFormat=”{}{0:C}”>




The ContentStringFormat property is available on ContentControl, ContentPresenter, and TabControl.


There’s an analogous HeaderStringFormat for HeaderedContentControl, GridViewColumn, GroupStyle, and HeaderedItemsControl.  Again, these are all cases where there is an analogous HeaderTemplate property.


Finally, there’s an ItemStringFormat on ItemsControl (the base class for ListBox) that allows you to format items.  For example, this produces a ListBox with two entries, “1,234.00” and “5,6789.00”:


<ListBox ItemStringFormat=”{}{0:N2}”>







Multi Bindings


All of the examples so far reference the bound value with some form of “{0}”, which is the zero-th index into the array of sources.  With a MultiBinding, you can actually get more than one input.  For example, the following has a TextBlock that composes the value in two other TextBlocks (in a real-world example, those would probably be TextBox’s for user input):


<TextBlock Name=”First”>Fred</TextBlock>

<TextBlock Name=”Last”>Flintstone</TextBlock>


<TextBlock >


        <MultiBinding StringFormat=”Name: {1}, {0}“>

            <Binding ElementName=”First” Path=”Text”/>

            <Binding ElementName=”Last” Path=”Text”/>





This produces “Name: Flintstone, Fred”.





All of the examples so far have been in US English (“en-US”).  But you can pick the culture for StringFormat, the same way that you pick culture for the Binding.Converter property.  That is, you can set it explicitly on the Binding, as in:


<TextBlock Text=”{Binding ConverterCulture=’en-US’, StringFormat='{}{0:N2}’ }” />


… which gives me “123.00” (note the period for the decimal separator), or as in:


<TextBlock Text=”{Binding ConverterCulture=’fr-FR’, StringFormat='{}{0:N2}’ }” />


… which gives me “123,00” (note the comma for the decimal separator).


Or you can specify it on the element in the Language property, as in:


<StackPanel Language=”fr-FR”>

    <TextBlock Text=”{Binding StringFormat='{}{0:N2}’ }” />



As an aside, note that the xml:lang attribute is mapped to the Language property.  So the above is equivalent to:


<StackPanel xml:lang=”fr-FR”>

    <TextBlock Text=”{Binding StringFormat='{}{0:N2}’ }” />




More Samples


Finally, see Lester’s post for more StringFormat examples.



Comments (7)

  1. Mark says:

    Thanks! I was trying to find some good examples for multi-property string formatting.

  2. Daniel Rose says:

    Unfortunately, there is a bug in WPF, considered "by design" by Microsoft. If you don't specify the culture in the binding, it will always use en-US, regardless of the user's setting for CurrentCulture. See…/wpf-binding-uses-the-wrong-currentculture-by-default

  3. mvashkev says:

    {Binding MyProperty, StringFormat={}{0}:}, to produce "<MyProperty>:" output, does not work, for some reason. Somehow the parser does not like the colon at the end. Another Microsoft bug, I guess. The alternative ContentStringFormat="{}{0}:" works as expected.

  4. Kamal says:

    Excellent article. crux points pointed out.

  5. leila says:

    thank you very problem was solved.