While working on a little MVVM thingy the other day, I ran into a sweet little piece of code that I wanted to share. I have seen several version of this around the web, but this is where I found this particular version. The piece of code gets rid of the ugly part of the INotifyPropertyChanged interface. The part where you use strings to identify what property has changed. I understand that that is how you have to do it, but it feels messy. A common solution is to add constants to hold the strings, but that is not a very much better solution. it is still messy. So how can we handle it in a safe way? Well…one idea would be to do it like this…
public class ViewModelBase : INotifyPropertyChanged
{
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
{
if (propertyExpression.Body.NodeType == ExpressionType.MemberAccess)
{
var memberExpr = propertyExpression.Body as MemberExpression;
string propertyName = memberExpr.Member.Name;
this.RaisePropertyChanged(propertyName);
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Instead of passing a string straight off, you use an Expression. This makes it safe. The way to call this would be like this: RaisePropertyChanged(() => MyProperty). Very elegant in my mind. The only issue would be that there is a lot of reflection going on, so it will be a lot slower. But to be honest, that is not a big problem in this case. It is not like it is something that will be called inside a loop with millions of iterations. At least it shouldn’t be…
Well…that was it. Just a simple little tip that I thought might be useful.
[UPDATE]
As there are a lot of comments regarding the performance implications of this implementation, I just want to make a little update.
First of all, for all the comments regarding IL emit and cool things like that, I just want to say that the idea with code is to keep it simple and precise. Your code should have a single responsibility. Adding IL emit code to your properties is wrong (at least in most cases, I have more about that later). And on top of that, you can’t do IL emit on Windows Phone 7 for example. So by using features like that, you are limiting your code reuse.
Next, I would like to ask if there really are performance issues here!? Let’s take a pretty common scenario. The user clicks a button, a command is called, the command executes some code that changes 2 properties that cause 2 property changed notifications. Those two notifications causes the UI to render something else on the screen. So with all of this happening (code executing, UI re-rendering and so on), will the property notification be the biggest problem? I actually don’t think so, I think that part of it is so small that you can ignore it. For the performance for different notification implementations, have a look here: http://www.pochet.net/blog/2010/06/25/inotifypropertychanged-implementations-an-overview/
Having that said, I do agree with the guy in the blog above. There are scenarios where you need to think about the performance. But that is not in you usual situation. It is in situations like live graphs and things like that, where you raise 200 notifications a second. In a scenario like that, of course you need to look at the performance. But in a normal VM scenario, you really don’t… And even in the extreme scenarios, I would probably try a coupe of different solutions to see how much they affected the performance.
And finally I want to remind some of you of the simple, yet very effective KISS pattern. Keep It Simple Stupid… Or even YAGNI, You Ain’t Gonna Need It. This is a perfect situation to start using those “patterns”. I do think that keeping it simple in the case of INotifyPropertyChanged would mean just using strings like normal, but let’s ignore that since you are going to need non string based functionality in a lot of cases. You are however not going to need the last bit of performance in most situations. So KISS and YAGNI basically tells us that we don’t need anything more complicated than the above code…at least that is how I interpret it.