Like a lot of others, I'm learning Silverlight, WPF and all the other facinating new technologies coming out of Microsoft (and elsewhere) these days. Most of this stuff is incredible, but occasionally you'll run into something that has a bit of a code smell about it. One of those is the INotifyPropertyChange interface in WPF and Silverlight.
In order to make data binding work in these two technologies, entities that have their data bound to WPF or Silverlight controls need to implement INotifyPropertyChanged in order to ensure that the controls are updated when the data in the entity changes. All well and good, but let's take a look at the interface:
// Summary:
// Notifies clients that a property value has changed.
public interface INotifyPropertyChanged
{
// Summary:
// Occurs when a property value changes.
event PropertyChangedEventHandler PropertyChanged;
}
Looks fine. And the PropertyChangedEventHandler delegate looks pretty standard... a sender and then a PropertyChangedEventArgs class that descends from EventArgs. But how do you indicate which property changed?
public PropertyChangedEventArgs(string propertyName);
A string matching the name of the property, passed into the constructor of the PropertyChangedEventArgs. So most people I've seen wind up implementing it everywhere something like this:
public string MyStringProperty
{
get
{
return _myStringProperty;
}
private set
{
_myStringProperty = value;
if( PropertyChanged != null )
PropertyChanged( this, new PropertyChangedEventArgs("MyStringProperty"));
}
}
If having a hardcoded string inside a property setter that has to match the name of the property doesn't constitute a "Code Smell" then I'm not sure I understand the concept.
Now, most people abstract the PropertyChanged null check down into a base class on their ViewModel objects in keeping with DRY.
private set
{
_myStringProperty = value;
RaisePropertyChanged("MyStringProperty");
}
Better, but the hard coded string is still there. What can we do about that?
Expression Trees to the rescue.
If you haven't dug into this technology yet, it's quite facinating. You build up a tree of expressions that does not have to be executed. It's a structure describing the code without actually executing it. This is how deferred execution in LINQ works and how LINQ to SQL is able to take your Where(...) and Select(...) calls and turn them into SQL statements.
In my base ViewModel class, I declare a delegate that is simply anything that returns an object:
public delegate object PropertyAccess( ) ;
And now I re-implement my RaisePropertyChanged method to take an expression which contains a PropertyAccess delegate:
protected void RaisePropertyChanged(Expression<PropertyAccess> propertyExpression)
{
MemberExpression getMemberExpression = propertyExpression.Body as MemberExpression;
if (getMemberExpression != null
&& getMemberExpression.Member.MemberType == System.Reflection.MemberTypes.Property)
{
RaisePropertyChanged(getMemberExpression.Member.Name);
}
}
OK... but how do you call it?
public string TestProperty
{
get
{
return _testProperty;
}
set
{
_testProperty = value;
RaisePropertyChanged(() => this.TestProperty);
}
}
But Ben! You're accessing TestProperty in the Setter! If there was real logic in there (for example, lazy loading some data), you might do all kinds of bad things!
No. The () => this.TextProperty call is never evaluated... it is only used to build an Expression tree which is then examined by the RaisePropertyChanged method, which extracts the appropriate property name.
The best part, in my mind? A magic string change becomes a compile time error. No more broken unit tests... in fact, probably no need for a unit test on every property set to ensure that the event is loaded.
I hope this was useful to you... I'll be back soon with more of my learnings. If you've got something you're curious about or a comment on this or any of my posts, please drop me a line using the comment feature!