11 Refactoring friendly WPF dependency properties

A custom dependency properties in WPF applications is usually looks like:

class MyControl : Control
{
   public Brush ForeGround
   {
      get { return (Brush)this.GetValue(ForeGroundProperty); }
      set { this.SetValue(ForeGroundProperty, value); }
   }
   public static readonly DependencyProperty ForeGroundProperty =
      DependencyProperty.Register(
        "ForeGround", typeof(Brush), typeof(MyControl));
}

There are a number of problems with that:

  • The return value of this.GetValue() requires a cast.
  • The type of the property may not match the value type of the Dependency Property. If one of them is changed, a runtime exception will be thrown.
  • The name passed to the DependencyProperty.Register may be different from the property’s name.

Making the calls to GetValue() and SetValue() type safe by redirecting them through a generic typed Property<> instance may reduce the complexity a bit.

Additionally, the property name can be derived from a lambda expression to support consistent refactoring scenarios:

  public Brush ForeGround
  {
    get { return ForeGroundProperty[this]; }
    set { ForeGroundProperty[this] = value); }
  }
  public static Property<Brush> ForeGroundProperty =
    new Property<MyControl, Brush>(c => c.Foreground);

That just looks a lot cleaner and fixes the problems above.

The code behind that is:

public struct Property<ValueT>
{
	Property(DependencyProperty prop)
	{
		_depProp = prop;
	}
 
	readonly DependencyProperty _depProp;
 
	public static implicit operator Property<ValueT>(PropertyBase prop)
	{
		return new Property<ValueT>(prop.DependencyProperty);
	}
 
	public static implicit operator DependencyProperty(Property<ValueT> prop)
	{
		return prop._depProp;
	}
 
	public ValueT this[DependencyObject obj]
	{
		get { return (ValueT)obj.GetValue(_depProp); }
		set { obj.SetValue(_depProp, value); }
	}
}
 
public abstract class PropertyBase
{
	public readonly DependencyProperty DependencyProperty;
 
	protected PropertyBase(DependencyProperty prop)
	{
		DependencyProperty = prop;
	}
}
 
public sealed class Property<ContainerT, ValueT> : PropertyBase
{
	public Property(Expression<Func<ContainerT, ValueT>> accessor)
		: base(DependencyProperty.Register(nameOfMember(accessor), typeof(ValueT), typeof(ContainerT)))
	{
	}
 
	static string nameOfMember(Expression<Func<ContainerT, ValueT>> expression)
	{
		var memberexp = expression.Body as MemberExpression;
		if (memberexp == null)
			throw new ArgumentException("Failed to get name of expression member", "expression");
		return memberexp.Member.Name;
	}
}

Two comments:

  • Property<> can implicitly used as DependencyProperty, just in case it needs to be passed to another method.
  • Memory consuption is the same, Property<> is a struct, just holding a reference to the registered DependencyProperty instance. The one additional temporary object is forgotten by the GC.