Silverlight/WPF: Implementing PropertyChanged with Expression Tree 15

Source Code: RaisePropertyChangedExample.zip [94.4 KB]

Credits: Thanks to Paul Strong and Soe Moe for sharing this code with me.

Introduction

This article will show you how to implement INotifyPropertyChanged interface with Expression Tree. I’m sure that the most of WPF/Silverlight developer are already familier with implementing INotifyPropertyChanged interface because this is the most important thing that you have to do when you want to notify the changes of property value to the Clients. But here is with Expression Tree. The most of us used to pass the property name as a string to the PropertyChanged event. Why Expression Tree here? Passing the property name as a string doesn’t just work? No, it works but passing a string is not safe. what if you forget to update the string if you are re-naming the Property. The compiler won’t remind you that you have failed to update the string. Of course, you can verify the name like Josh mentioned in his article. But still, you will know only when you run the program. This is where Expression Tree come in. You can use VS Reflector to rename when you are changing the property name. If not, the compiler will remind you to change.

Let’s take a look at the first sample. The class “PageViewModel” implements INotifyPropertyChanged event just as the way that we always do. There is no super cool things inside.


public class PageViewModel : INotifyPropertyChanged
{
private string name = string.Empty;

public string Name
{
get
{
return name;
}
set
{
name = value;
this.RaisePropertyChanged("Name");
}
}

public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

But if you are developing the project, there won’t be just one class so implementing INotifyPropertyChanged become tireding process. So, I would suggest to create a base class ( I will call it “ObservableBase ” in this article) so that all classes that need to be implemented INotifyPropertyChanged interface can inherit from that class.


public abstract class ObservableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;

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

After creating a base class as above, we can change our PageViewModel to inhert from base class so we can completely remove all codes that we used for implementing INotifyPropertyChanged event.


public class PageViewModel : ObservableBase
{
private string name = string.Empty;
public string Name
{
get
{
return name;
}
set
{
name = value;
this.RaisePropertyChanged("Name");
}
}
}

But we are still passing the string to RaisePropertyChanged method. How should we change it to Expression Tree? Yes, we will need to change our base class a little bit. The first thing that come into my mind is that to add one more event that can accept the expression. Let’s check out the sample below.


public void RaisePropertyChanged<TValue>(Expression<Func<TValue>> propertySelector)
{
if (PropertyChanged != null)
{
var memberExpression = propertySelector.Body as MemberExpression;
if (memberExpression != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(memberExpression.Member.Name));
}
}
}

After changing this, we can call that method from setter as below.


private string name = string.Empty;
public string Name
{
get {
return name;
}
set {
name = value;
this.RaisePropertyChanged<string>( () => this.Name);
}
}

But why <string>? Is there any way to avoid this? My friend, Soe Moe, come up with the solution that uses C# extension method to avoid having the generic type defined in setter. It’s pretty cool. Please check-out the extension method below.


public static class ObservableBaseEx
{
public static void RaisePropertyChanged<T, TProperty>(this T observableBase, Expression<Func<T, TProperty>> expression) where T : ObservableBase
{
observableBase.RaisePropertyChanged(observableBase.GetPropertyName(expression));
}

public static string GetPropertyName<T, TProperty>(this T owner, Expression<Func<T, TProperty>> expression)
{
var memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
{
var unaryExpression = expression.Body as UnaryExpression;
if (unaryExpression != null)
{
memberExpression = unaryExpression.Operand as MemberExpression;
if (memberExpression == null)
throw new NotImplementedException();
}
else
throw new NotImplementedException();
}

var propertyName = memberExpression.Member.Name;
return propertyName;
}
}

Finally, we can call the RaisePropertyChanged event without specifing any generic type. Cool, huh?


private string name = string.Empty;
public string Name
{
get {
return name;
}
set {
name = value;
this.RaisePropertyChanged( p => p.Name);
}
}

Yes. I’m open to any better solution that you have. Please feel free to let me know if you have better idea. You can also download my sample (both WPF and Silverlight included in zip) and play a bit as well. :)

Thanks for reading!

References

15 thoughts on “Silverlight/WPF: Implementing PropertyChanged with Expression Tree

  1. Reply Michael Brown Apr 9,2009 5:35 pm

    Hey there,
    I blogged a similar solution a month or so ago. I went to the extreme to eliminate the need for a base class…there were some limitations pointed out with my implementation however so I labeled it as a neat trick for the time being.

    http://azurecoding.com/blogs/brownie/archive/2009/02/23/static-reflection-say-what.aspx

  2. Reply Brian Apr 17,2009 4:28 am

    Very nice, I really disliked the idea of using strings to notify property changes!
    Do Expression Trees use Reflection to perform these tricks? Just wondering as I generally try to avoid using Reflection at all costs.

  3. Reply Vivek Apr 17,2009 11:04 pm

    Nice approach!
    However I feel that this approach can be further refined taking advantage of the C# automatic properties and AOP(Aspect Oriented Programming).
    Use this link for reference http://richardsbraindump.blogspot.com/2009/02/aspect-oriented-programming.html.

  4. Reply Roko Apr 30,2009 3:25 pm

    Hei Mike,

    Good approach. You get rid off of passing hard coded string as property name which is good for producing clean code and killing the chance of mistyping the property name when raising the PropertyChanged event.

    Only one concern, If performance is a key issue then Expression Tree based solution in this context will have some performance penalties as reflection is involved during the decoding of expressions. And that PropertyChanged event will get called countless times during your application life cycle. In this scenario you get best possible performance by passing hard coded string as property name. But off course that hard coding doesn’t look cool and can be error prone.

    For now I only see one better solution that avoids both reflection at runtime and hard coded property name in your code as well; and that is by using postsharp aspect to auto implement INotifyPropertyChanged interface in any classes. You also get rid off code to manually raise the event in your classes. Your code will look like this

    /* aspect that auto implements INotifyPropertyChanged. You need to create it by overriding existing post sharp aspect */

    [NotifyPropertyChanged]
    public class Person
    {
    public string Name{ get; set; }
    public int Age { get; set; }
    }

    Looks much cleaner right ?

    The attribute/custom aspect will auto implement INotifyPropertyChanged for every single property you have and works excellent with WPF data binding without adding any extra performance overhead.

    In case you are interested about listening to that propertychanged event from other classes you can do it like that….

    INotifyPropertyChanged P = Person as INotifyPropertyChanged;
    P.PropertyChanged += (sender, arg) => { /* Your Event handling code goes here */ };

    - Roko

  5. Reply Michael Sync May 3,2009 8:47 am

    Hey Roko!! good to see you here… thanks for dropping by! man :)

    >>If performance is a key issue then Expression Tree based solution in this context will have some performance penalties as reflection is involved during the decoding of expressions

    I think reflection and Expression Tree are different things. I’m not sure whether there are some performance penalties on using Expression Tree. Anyway, you brought good point. I will dottrace the performance..

    We can use [NotifyPropertyChanged] attribute with PostSharp or Interception. But I personally don’t like PostSharp that much since it makes my VS very slow.

    Interception (e.g. Unity Interception) might be good too but I haven’t tried it yet. I found some samples that are using Unity Interception for that purpose..

  6. Pingback: Michael Sync » An Early Look at Silverlight Model-View-ViewModel Toolkit 1

  7. Reply jsp3536 Jun 15,2009 11:44 am

    Michael,

    Did you ever run any test showing the performance impact on using the expression tree rather then just passing in the string name?

  8. Reply Michael Sync Jun 15,2009 11:46 am

    Hi,

    Yes. I did it. Please take a look at my comments from this post. There are two of my comments that I mentioned about the comparison.

  9. Pingback: Avoiding string while raising or handling PropertyChanged event « Mehroz’s Experiments

  10. Reply Oded Levy Sep 25,2009 3:32 am

    Hi there,

    Very nice work indeed. Though due to delegate inference you can eliminate the need for expressing the generic parameter type without extension methods. For example instead of writing:

    this.RaisePropertyChanged( () => this.Name);

    you can write:

    this.RaisePropertyChanged( () => this.Name);

    Regards

  11. Reply Oded Levy Sep 25,2009 3:35 am

    In my previous comment i meant instead of writing:

    this.RaisePropertyChanged( () => this.Name);

    you can write:

    this.RaisePropertyChanged( () => this.Name);

    Regards

  12. Pingback: Raising the right PropertyChanged with C# 5′s Caller Info Attributes « Rob’s Tech Blog

  13. Pingback: Tip: Modern INotifyPropertyChanged « I had this idea once…

Leave a Reply