Why Silverlight Binding’s StringFormat Property Sometimes Isn’t Fully Working

In Silverlight 4, the new Binding property StringFormat was introduced. It’s a nice thing, e.g. if you want to display numeric values with digit grouping and a fix number of decimal places. The syntax is equal to the String.Format: {Binding DataContextProperty StringFormat=’#,##0.00′}. One can, of course, use it for other simple types like DateTime…

I was using this feature in a project in one control, and it worked as expected. Then I created a new UserControl, and the trouble began. When the control showed up, the value was display as set by the StringFormat expression set in the xaml file. But after entering a new value, the formatting was gone.

It took me some time to figure out what the difference was. And it was not found in the xaml!

What I noticed was that the control working correctly as long as it was bound against a property of a class that was generated from a WCF Service Reference. Means, this class was originally declared inside the WCF Service assembly, and because it was part of the operation contract declared by the WCF Service, VS generated that class (or kind of proxy) in the Silverlight project as well.

When I bound the newly created control to an instance of this operation contract class, without changing the xaml, everything worked as expected.

So what is the difference? First of all, I bound the new control to (a property of) an instance of a class that was declared inside the Silverlight project itself.

The class looked like this:

public SilverlightClass
{
public decimal Value { get; set; }
}

Comparing it to the operation contract class, first thing I noticed was that that class not only had properties, but it had also data members (fields) which are encapsulated by corresponding properties.

So I changed the Silverlight class to something like this:

public SilverlightClass
{
private decimal m_Value;

public decimal Value
{
get { return (m_Value; } set { m_Value = value; } }
}

But still, the formatting did not work. So I “copied” the other difference: the operation contract also implemented the INotifyPropertyChanged interface and raised a PropertyChanged event whenever a property was set to a new value. This lead to the final version of the Silverlight class:

public SilverlightClass : INotifyPropertyChanged
{
private decimal m_Value;

public decimal Value
{
get { return (m_Value; }
set
{
if (!m_Value.Equals(value))
{
m_Value = value;
RaisePropertyChanged("Value");
}
}
}

public event PropertyChangedEventHandler PropertyChanged;

private void RaisePropertyChanged
(
string propertyName
)
{
if ((PropertyChanged != null))
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
}

And that was it… Since my knowledge of Silverlight and its mechanisms is very little, I was a little bit surprised.

Having the Silverlight class changed like that, also the update of the bound controls worked when the code behind changed the bound property of the DataContext during runtime (e.g. by a LostFocusHandler).