March 29, 2009

Implementing INotifyPropertyChanged without hard-coded strings

If you are programming with the Windows Presentation Foundation you probably also use data binding and the INotifyPropertyChanged interface. By implementing it, objects can notify controls about changed data. A typical implementation looks like this:

using System.ComponentModel;

public class NotifyPropertyExample : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };

internal void FireNotifyPropertyChanged(string propertyName)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

private string example;
public string Example
{
get { return this.example; }
set
{
this.example = value;
FireNotifyPropertyChanged("Example");
}
}
}

The interface INotifyPropertyChanged defines a single event, which takes the name of the changed property as a parameter. In the example the event is fired in the setter method of the property, passing the name of the property as string.

This works. But there are a few drawbacks here:
  • There is no auto-completion for the property name string. You have to type it.
  • The compiler cannot validate that you typed the string correctly.
  • Even during run-time a typo usually remains unnoticed. If you don't take special actions there are no exceptions thrown.
  • Code may break on refactorings. When you rename the property you have to take care the string is changed too.
Therefore implementing INotifyPropertyChanged this way can lead bugs. Nasty bugs, as they are really hard to track down.

So what to do instead?

A common way to tackle this problem (see e.g. here or here) is to use Linq expressions. Here is what I do in my code:

using System.ComponentModel;
using System.Linq.Expressions;

public class NotifyPropertyChangedBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };

internal void InternalFireNotifyPropertyChanged(string propertyName)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

public static class NotifyPropertyChangedBaseExtensions
{
public static void FireNotifyPropertyChanged<T, R>(this T obj,
Expression<Func<T, R>> expr)
where T : NotifyPropertyChangedBase
{
obj.InternalFireNotifyPropertyChanged(((MemberExpression)expr.Body).Member.Name);
}
}
First I create a base class that implements INotifyPropertyChanged. Nothing special with that. The magic kicks in with the extension method FireNotifyPropertyChanged. It extends NotifyPropertyChangedBase or a derived class and takes a Linq expression as a parameter.

This looks complicated but is straight forward to use. The example above can be rewritten as follows:

public class NotifyPropertyExample2 : NotifyPropertyChangedBase
{
private string example;
public string Example
{
get { return this.example; }
set
{
this.example = value;
this.FireNotifyPropertyChanged(o => o.Example);
}
}
}
FireNotifyPropertyChanged has to be implemented as an extension method (rather than doing it in the base class) as the expression has to use your derived class to know about its properties. This way also IntelliSense works nicely.

Any disadvantages doing it this way? Yes, there is a small performance hit. An extra method call and building up the expression. So for objects whose updates are performance critical I would test if this is a problem. But for most use cases I would say that the advantages clearly weigh more heavily.
blog comments powered by Disqus