INotifyPropertyChanged

When we want to use binding with WPF or SL, we use INotifyPropertyChanged interface most of time.

This interface has only one member:

event PropertyChangedEventHandler PropertyChanged;


We generally use it like this:



protected virtual void RaisePropertyChanged(string property)
{
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(property));
}


I advise against doing it! Indeed, I refuse to use the property name as a string (possible typos, no refactoring on property renaming, error only on execution). The worst in this case is the fact that if we have an error, even on execution, we won’t have an exception, and we can lose several minutes to understand why the bound control is not refreshed when the property changes.



So my idea is to use the name of the property by code.



We can use Expression Trees for this:



public void RaisePropertyChanged<T>(Expression<Func<T>> exp)
{
    string propertyName = PropertyName.GetPropertyName(exp);
    if (propertyName != null)
        RaisePropertyChanged(propertyName);
}


public static class PropertyName
{

    public static string GetPropertyName(LambdaExpression exp)
    {
        var memberExpression = exp.Body as MemberExpression;
        if (memberExpression != null)
            return memberExpression.Member.Name;
        return null;
    }
}


Now instead of this:



RaisePropertyChanged("MyProperty");


I will write the following:


RaisePropertyChanged(() => MyProperty);




It’s better.



Then, what about factorization. Indeed, we don’t want to have to write this code on each class (with properties used for binding). We can use inheritance but, as C# doesn’t support multi-inheritance, I don’t think it’s a good idea and I prefer encapsulation in this case.



public class NotifyPropertyChanged
{
    private Func<PropertyChangedEventHandler> _getRaiseEvent;
    private object _sender;

    public NotifyPropertyChanged(object sender, Func<PropertyChangedEventHandler> getRaiseEvent)
    {
        _getRaiseEvent = getRaiseEvent;
        _sender = sender;
    }




   
public void RaisePropertyChanged(string propName)

    {
        PropertyChangedEventHandler propertyChanged = _getRaiseEvent();
        if (propertyChanged != null)
            propertyChanged(_sender, new PropertyChangedEventArgs(propName));
    }
    public void RaisePropertyChanged<T>(Expression<Func<T>> exp)
    {
        string propertyName = PropertyName.GetPropertyName(exp);
        if (propertyName != null)
            RaisePropertyChanged(propertyName);
    }

}


Now, the class which implements INotifyPropertyChanged just has this code (which can, of course, be factorized on a base class (ViewModelBase for example)):



public event PropertyChangedEventHandler PropertyChanged;


private NotifyPropertyChanged _notifyPropertyChanged;
protected NotifyPropertyChanged NotifyPropertyChanged
{
    get { return _notifyPropertyChanged ?? (_notifyPropertyChanged = new NotifyPropertyChanged(this, () => PropertyChanged)); }
}


And we can use it like this:


NotifyPropertyChanged.RaisePropertyChanged(() => MyProperty);

Hope that helps.

This entry was posted in 13461, 7671, 8708. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>