Friday, July 10, 2009

Statically Typed Dependency Properties

Recently, I found a nice post written by a friend of mine, regarding statically typed property names. His post can be found here. What I simply did was to put his concept into WPF world :)

Problem

Typical registration of a WPF's dependency property looks like follows:

public int MyInteger1
{
get { return (int)GetValue(MyInteger1Property); }
set { SetValue(MyInteger1Property, value); }
}

public static readonly DependencyProperty MyInteger1Property =
DependencyProperty.Register("MyInteger1", typeof(int), typeof(Window1));

Hmm, what's wrong with it ? It "breakes" the DRY (Don't Repeat Yourself) principle. Given code defines a property named MyInteger of type int, but this information is coded twice, in the property itself and during its registration. If you want to change the name or type of a single property, you have to update the code in two places.

Solution

Now consider the following code:

public int MyInteger2
{
get { return (int)GetValue(MyInteger2Property); }
set { SetValue(MyInteger2Property, value); }
}

public static readonly DependencyProperty MyInteger2Property =
DependencyPropertyHelper.Register<Window1>(t => t.MyInteger2);

What has changed here is the way the property is registered. Now, changing the name or the type of a property is done through its getter. Nice, isn't it ? This approach works with both regular and read only properties but does not with attached properties, because the latter does not use property to access its value but uses methods instead. Implementation behind the Register<TOwner> method used above is fairly simple and looks like this:

public static class DependencyPropertyHelper
{
public static DependencyProperty Register<TOwner>(
Expression<Func<TOwner, object>> property)
{
return DependencyProperty.Register(typeof(TOwner).GetPropertyName(property),
typeof(TOwner).GetPropertyType(property),
typeof(TOwner));
}
}

GetPropertyName and GetPropertyType methods come from the post I've mention at the beginning.

Full code can be downloaded from my code gallery.