Silverlight/WPF: Implementing PropertyChanged with Expression Tree

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

My blog is 3 years old now!

Note: This post has been posted with back date since I couldn’t write anything on that day.

Hey there!!

My blog is 3 years old now. It was so fast!! I’m still feeling the day that I started this blog. As I wasn’t that familiar with any blogging software, I did a lot of searches and experiments for the blogging platform that I’m  going to use for my little blog. I tried quite a few platforms including blogger, wordpress, typepad and etc and I chose to use wordpress for blog. Yes. I’m still happy with wordpress (both wordpress.com and wordpress.org ) until now and I believe that I make the right choice.

Here is the stats for last year.

Stats

  • 582602 page views this year (960,549 – 377,947)
  • 1600 to 2000 page views per day
  • 889 comments (2,850 – 1,961)

Award

Thank you so much!! guys.. I will keep on bringing new stuffs as much as I could. Please keep on watching.. :) Thanks again.

Here is one of my favorite “Happy Birthday” video from youtube. :) Enjoy!

Silverlight MVP (Most Valuable Professional) Award

Hello everyone!

I got MVP award for Silverlight this year. I’m really really happy about that.  (Thanks, god! It wasn’t April Fool! ).  Thanks so much, everyone! I would like to give my special thank to Justin Angel and Lilian Quek. I promise that I will try to contribute as much as I can for our community.

My MVP Public Profile : https://mvp.support.microsoft.com/profile=…9

mvplogo

As of now, there are five MVPs under Silverlight Expertise. I’m very happy to be one of them. I hope we will get more people in future. All the best for those who are interested to become Silverlight MVP!

silverlight-mvp-list-1