One of the great features introduced in .NET 3.5 Framework Service Pack 1 is the BindingBase StringFormat property. When used in a data binding expression the StringFormat property replaces most IValuteConverters that were used for formatting of values in WPF 3.0 & WPF 3.5 applications.
Here are two examples of the StringFormat property in action formatting a currency field:
<TextBox Text="{Binding Path=Salary, StringFormat=c}" /> <TextBox Text="{Binding Path=Salary, StringFormat=\{0:c\}}" />
Nullable Type in the Mix
If you are binding to a non-Nullable data type the above will work just fine.
However, if you are binding to a Nullable data type the above will not work.
This breaks down when a UI Control like a TextBox as a value and the user clears the TextBox and press TAB. The default implementation of StringFormat will attempt to set the Target Property to an empty string which in the the case of a Nullable Decimal property will cause the following or similar data binding exception. The below data binding exception can be viewed in the Visual Studio Output window.
Exception
System.Windows.Data Error: 7 : ConvertBack cannot convert value ” (type ‘String’). BindingExpression:Path=Age; DataItem=’Customer’ (HashCode=31884011); target element is ‘TextBox’ (Name=”); target property is ‘Text’ (type ‘String’) FormatException:’System.FormatException: Input string was not in a correct format.
at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
at System.String.System.IConvertible.ToInt32(IFormatProvider provider)
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at MS.Internal.Data.SystemConvertConverter.ConvertBack(Object o, Type type, Object parameter, CultureInfo culture)
at System.Windows.Data.BindingExpression.ConvertBackHelper(IValueConverter converter, Object value, Type sourceType, Object parameter, CultureInfo culture)’
TargetNullVaue to the Rescue
In the above example, the exception is thrown because of a type mismatch. In WPF 3.0 and 3.5 I had a set of Nullable ValueConverters for my applications to handle this problem.
Another great feature introduced in .NET 3.5 Framework Service Pack 1 is the BindingBase TargetNullValue property. This property can be used to handled the type mismatch problem when converting an empty string from a TextBox to Nothing (null) when the binding pipeline sets the target Nullable property.
Let’s have a look at the two below TextBoxes.
<TextBox Grid.Column="1" Grid.Row="1" Margin="0,11,11,11" VerticalAlignment="Top" Text="{Binding Path=NumberOfComputers, TargetNullValue={x:Static sys:String.Empty}, StringFormat=\{0:D\}}" /> <TextBox Grid.Column="1" Grid.Row="2" Margin="0,11,11,11" VerticalAlignment="Top" Text="{Binding Path=Age, StringFormat=\{0:D\}}" />
These TextBoxes are both bound to Nullable properties. The first TextBox takes advantage of the TargetNullValue property and works as expected. The second does not. The data binding pipeline will throw an exception when the second TextBox is changed to an empty string and it attempts to assign the value of String.Empty to the Target property.
Here is a potential problem. If the exception gets thrown and swallowed because the code didn’t check for this, the user thinks they cleared a value but the property the TextBox is bound to never gets changed due to the exception being thrown.
Download
I’ve included a very simple project that you can download a play with.
After downloading the project, please change the extension from .doc to .zip. This is a requirement of WordPress.com.
Download Sample Project (25KB)
Steps To Reproduce Issue
Launch included program using debug mode.
Ensure Visual Studio Output window is visible.
Set each TextBox to 7.
Go to first TextBox. Clear field and press TAB. Notice nothing is added to the Output window.
Go to second TextBox. Clear field and press TAB. Notice nothing an exception is added to the Output window.
Close
When binding to Nullable types, use the TargetNullValue property along with the StringFormat property to avoid type mismatch exceptions.
Hope this tip has helped you learn more about WPF!
Have a great day!
Just a grain of sand on the worlds beaches.



September 30, 2009 at 2:25 pm |
Hi Karl, that’s really good. Is it possible to change CultureInfo for this Binding..StringFormat syntax?
October 1, 2009 at 10:23 am |
StringFormat should pick up your threads CultureInfo automatically the same way the applicaiton does.
Are you switching cultures after the applicaiton starts or are you forcing a culture on appliation startup?
If so, read the article Josh Smith and I wrote on Code Project. The International Wizard article. We show how to propertly set the culture on application startup. There is a special line of code you have to add to get the WPF data binding system to work with the new culture.
Cheers,
Karl
October 5, 2009 at 9:16 pm |
Hi Karl, I may say that I started on WPF after reading your articles here. I am your brazilian fan! I’m sure you know much more tricks to make things work better. There’s a lot of work to do in order to improve WPF controls, but’s it’s a good start.
About my issue, indeed I was changing the culture after the application was started.
The bottom line is that some users mess with current culture. This happens anytime you have people from different countries, and they want to use your application. Now you can imagine why I had to force culture. In Brazil and Colombia the decimal point is comma, in Mexico is like US, they use a “dot”.
When displaying these formatted numbers, I saw differences: some notebooks has a Thread CurrentCulture as en-US, others es-CO, es-MX, and so on.
My goal was to unify the way people enters a decimal number in WPF app source code to use always a dot as decimal point.
I’m aware how to use resources files and globalization in Win32 app, now it’s time to start using it on WPF, I saw on http://www.codeproject.com/KB/WPF/InternationalizedWizard.aspx that it’s posible, and a little different, but’s it’s fine.
Tell me what do you think about this: if we can’t change people’s culture configuration, is it ok to force it to a specific format? or… should we use a numeric format preseted in a resource file?
thank you again for helping, much appreciated!!
Junior
October 6, 2009 at 9:41 am |
The problem with straying off the well known path is glitches always popup. But, now I understand your delima.
You “could” not use stringformat and instead, use a converter to perform some custom formatting.
Hope this helps,
Cheers,
Karl