WPF dependency properties

This article was originally published in VSJ, which is now part of Developer Fusion.
I tend to find, after working with a technology for a while, that I tend to take a lot of its more mundane features for granted. Prompted by a recent discussion with some colleagues, I was reminded that one of those features that I’d been ignoring was the humble Dependency Property (DP). So in this article, I want to take you on a guided tour of the DP and then show you how to use (and abuse) it to accomplish code injection into your WPF applications.

An introduction to Dependency Properties

The two main .NET languages, C# and Visual Basic, have had support for properties since their inception; and we happily used them in our Windows Forms and ASP.NET applications without any real complaints. So why did the WPF team feel the need to invent another property system?

Let’s look at a quick example to see why they’re so useful.

Figure 1 shows a screenshot of a simple WPF user control that provides a rudimentary login interface.

Figure 1
Figure 1: The LoginControl in action

I grant you that the LoginControl is not much to look at, but aesthetics are not what I want you to focus on at this point. Instead, I’m going to pick apart the XAML that I used to create this control to show you just some of the features of a DP.

Sparse property storage

Properties are small, right? After all, if I chose to write a Button class with a simple Width and Height property, how much memory would an instance require?
public class Button {
	public double Width { get; set; }
	public double Height { get; set; }
}
The problem here is that those innocuous-looking properties all require a small amount of storage for each and every object, even if I choose to let them stay at their default values; and the real WPF Button class, along with all of its brother and sister controls, has an awfully large number of properties.

The first benefit of a DP is that a value is only stored for an object if it’s specifically been set. Under the covers, a dictionary of property/value pairs is used, resulting in a much smaller amount of storage in the typical case where most of the values for properties are not explicitly set on the control, but are left at the defaults. In reality, the DP implementation is far more complex than just using a mere dictionary, as you can imagine when you look at some of the other features on offer.

Property inheritance

To begin with you’ll notice that all of the elements in Figure 1 are using the same FontFamily (in this case MS Sans Serif) and FontSize (14pt). Rather than have to set these values on every control, they can be set in just one place, the containing grid, as shown below:
<Grid
	TextElement.FontFamily="MS Sans Serif"
	TextElement.FontSize="14pt">
	...
</Grid>
Now this form of property inheritance is nothing new; we’ve seen it before going as far back as Visual Basic, or with ActiveX controls reading property values from their containers. You might even argue that you’ve seen the same behaviour in Windows Forms, but a quick look at the Font property of the Control class, shown the listing below will surely tell you that this is not the sort of code that you want to be writing in your own .NET types.
public virtual Font get_Font()
{
	Font font = (Font)
	this.Properties.GetObject(PropFont);
	if (font != null)
	{ return font; }
	Font parentFont =
		this.GetParentFont();
	if (parentFont != null)
	{ return parentFont; }
	// ActiveX ambient code elided for
	// sanity
	return ...;
}
It’s also important to remember here that property inheritance is not inheritance in the OO sense; it’s about obtaining the value of a property from a parent element in the tree.

Expressions

Another interesting feature of a DP is its ability to work with expressions (and I don’t mean the design suite from Microsoft). Take a quick look at the XAML for the username Label.
<Label ... Target="{Binding
	ElementName=txtUsername}">
_Username:</Label>
This is pretty darn interesting, because it’s using a Binding expression to resolve the value as and when it’s needed. Expressions allow us to build data-bound UI. In fact, one of the most important things to remember with data binding in WPF is that the target of the binding must be a DP, because standard .NET properties can’t support expression resolution.

Styles and Templates

Notice the Login Button in Figure 1 is an attractive (says who?) green button, unencumbered by the normal Windows styling. A quick look at the XAML reveals that its appearance is controlled by a style and a template, as shown below:
<Grid.Resources>
	<Style TargetType="Button">
		<Setter Property="Background"
			Value="Green" />
		<Setter Property="Foreground"
			Value="White" />
		<Setter Property="Template">
			<Setter.Value>
				<ControlTemplate TargetType="Button">
					<!-- template elided for clarity -->
					...	
				</ControlTemplate>
			</Setter.Value>
		</Setter>
		... <!-- more to come -->
	</Style>
</Grid.Resources>
The fact that you can apply a style or template to a control is interesting, but what’s really clever is that way that when WPF needs to render the Button it reads the value of the Background and Foreground properties from the Style, without you having to write a single line of code. That’s cool.

Animation

The modern button would be nothing without a cool rollover effect, and our Button is no exception, as you can see in Figure 2.

Figure 2
Figure 2: A cool animated mouse rollover effect

The exciting thing here is that the background doesn’t merely go blue; it animates the colour change over a fraction of a second, using the following trigger-based animation:

<Style.Triggers>
	<Trigger Property="IsMouseOver" Value="true">
		<Trigger.EnterActions>
			<BeginStoryboard>
				<Storyboard>
					<ColorAnimation Duration="0:0:0.25"
			Storyboard.TargetProperty="Background.Color" To="Blue" />
				</Storyboard>
			</BeginStoryboard>
		</Trigger.EnterActions>
		<Trigger.ExitActions>
			<BeginStoryboard>
				<Storyboard>
					<ColorAnimation Duration="0:0:0.25"
						Storyboard.TargetProperty="Background.Color" />
				</Storyboard>
			</BeginStoryboard>
		</Trigger.ExitActions>
	</Trigger>
</Style.Triggers>
There are a number of clever aspects to this. The first is, of course, that this animation requires no code on our part. However, the really clever bit is that way that the animation resets the background back to its original value when the mouse rolls off. The ColorAnimation simply has a Duration and a TargetProperty, but no target value to animate to. Wow! This implies that the real value of the property must be being maintained somewhere even though the two, completely unrelated animations are “changing” it.

Extending a type with an attached property

There’s a common OO mantra that states that types should be open for extension but be closed for modification. In other words, we should be able to add functionality to a type without having to change its implementation. Dependency properties do this through a variation known as an attached property.

Hopefully you’re comfortable with the idea that the value of a DP is attached to an object through some form of dictionary with a bit of extra cleverness to boot. This means that the type only needs to know about the dictionary, not the specific properties. Let’s look at an example:

<Button Grid.Column="1" Grid.Row="2" ... >Login</Button>
Buttons, in keeping with all other elements, don’t care about their containing element. After all why should they? So they don’t have properties for their position in a Grid, StackPanel or even a Canvas. If they did, then every time a new panel was produced all of the FrameworkElement types would need to be modified, and that would break our OO mantra. Therefore, one way to think about the XAML above is that the Button is being asked to store in its property dictionary values that will be read by the Grid, not by the Button itself, so that the Grid can know into which column and row it should put the Button.

Coercion and validation

Just about every WPF application has at least one Slider, or equivalent control, to perform zooming. As you can see from Figure 3, even Visual Studio 2008 gets in on the act in the XAML Design View.

Figure 3
Figure 3: Every application needs a zoom slider!

The problem with a control such as Slider is that it has three interrelated properties: Minimum, Value and Maximum. You might reasonably expect that Minimum <= Value <= Maximum at any one time. So it might come as a surprise that the following is perfectly legal, if a touch daft.

<Slider Minimum="1" Value="20"
	Maximum="5" x:Name="mySlider" />
I know that this XAML is a little bit artificial, but if you think about it from the point of object initialisation then you can see that this situation can occur quite easily. In Windows Forms, for example, the Slider’s analogue, TrackBar, has to implement the ISupportInitialize interface to ensure that it maintains a consistent state. Otherwise it would have to rely on enforcing a specific code sequence in order to maintain consistency such as this:
trackBar.Maximum = 5;
trackBar.Minimum = 1;
trackBar.Value = 20;	// throw an out of
								// range exception
WPF controls don’t have this problem. A DP supports coercion of a value so that it always makes sense. For example, if you ask the Slider for its Value after the XAML shown previously has been loaded, it will return the value 5. Simply put, the Slider coerced the out-of-range value down to the Maximum allowed.

What’s really neat about coercion, though, is that if you then alter the Maximum property of the Slider up to, say, 50, and then ask the Slider for its value it will return 20. This tells you that the original value is still being stored. Under the covers, the Slider (actually its base class, RangeBase) tracks any changes made to the Maximum and Minimum DPs, using the in-built support that DPs offer for reporting changes, and then forces WPF to coerce the Value property by calling the control’s CoerceValue() method.

Somewhat closely coupled to the idea of coercion is validation. DPs provide a callback mechanism to allow validation to be performed. You’ll see how this fits into the DP pipeline a little later on.

Registering a DependencyProperty

So DPs are great, full of wonderful features, and you’ve now decided that you’ve just got to use them in your components. There are two key parts to using a DP:
  1. deriving (directly or indirectly) from the DependencyObject base class, and
  2. registering a static DependencyProperty field in your class.
Here’s the code for a Username DP for the LoginControl:
public partial class LoginControl :
	UserControl
{
	public static readonly
		DependencyProperty UsernameProperty
		= DependencyProperty.Register(
		"Username", typeof(string),
		typeof(LoginControl));
}
The three pieces of information passed into the Register() method are the “name” of the property, its type and the type that is the owner of the property. You should also follow the naming convention for DPs, whereby the field has a matching name to that of the property (but with “Property” appended, of course), which is shown above.

With this code in place, clients can now set and get the value of the DP as follows:

LoginControl lc = new LoginControl();
lc.SetValue(
LoginControl.UsernameProperty, "dave" );
string user = (string) lc.GetValue(
	LoginControl.UsernameProperty);
The GetValue() and SetValue() methods are provided by the base DependencyObject class. As you can imagine, this form of code rapidly becomes tedious to write, so it is highly recommended (a polite way of saying mandatory) that you wrap the DP with a standard .NET property, as shown below.
public class LoginControl : UserControl
{
	public string Username
	{
		get { return (string)GetValue(
			UsernameProperty); }
		set { SetValue(UsernameProperty,
			value); }
	}
	// rest of class is elided for clarity
	...
}

The property trap

Wrapping a DP with a standard .NET property certainly makes it easier to work with a DP from code. However, there is a potential trap that you can fall into. Many of the features of WPF call the SetValue() and GetValue() methods directly. Therefore, you must never place additional functionality into the get{} or set{} blocks of the property wrapper. You’ll see how to add extra validation or handle change notification a little later on.

Creating attached properties

The most likely scenario for using an attached property is when you’re writing a custom layout panel, and you want to inject layout information into other controls. Registering an attached property is very similar to registering a standard DP, but there are two differences:
  1. You must call the static RegisterAttached(), and
  2. You provide static GetPropName() and SetPropName() methods instead of a property accessor
The code below shows how to register (and then use) an IndentLevel attached property for a custom panel that produces an indented layout:
public class IndentPanel : Panel
{
	public static double GetIndentLevel(
			DependencyObject obj)
	{
		return (double)obj.GetValue(
			IndentLevelProperty);
	}
	public static void SetIndentLevel(
		DependencyObject obj, double value)
	{
obj.SetValue(IndentLevelProperty, value);
	}
	public static readonly
		DependencyProperty
		IndentLevelProperty =
	DependencyProperty.RegisterAttached(
			"IndentLevel", typeof(double),
			typeof(ownerclass));
// measuring & arranging code not shown
	...
}
// Using the IndentLevel property (in C#)
IndentPanel ip = new IndentPanel();
Button btn = new Button();
IndentPanel.SetIndentLevel( btn, 3 );
...
<!-- using the IndentLevel property
	(in XAML) -->
<local:IndentPanel xmlns:local="...">
	<Button IndentPanel.IndentLevel="3"
		... />
</local:IndentPanel
You’ll also see how you can use attached properties to inject code into types at the end of this article.

A few tips

Writing DPs can be incredibly tedious. Fortunately, there are a couple of snippets that you can use to help you in Visual Studio; namely propdp (to create a DependencyProperty) and propa (for attached properties).

There is one tiny, but deeply annoying thing that you have to watch out for with these snippets: they both use an overload of the Register() (or RegisterAttached()) method that takes a fourth parameter that lets you specify a default value for the property that you’re registering.

The code below shows the result of using the propdp snippet to add a MinPasswordStrength DP to the LoginControl. Note the fourth parameter initialising the default value to 0.

public static readonly DependencyProperty
	MinPasswordStrengthProperty = DependencyProperty.Register(
		"MinPasswordStrength", typeof(double),
		typeof(LoginControl), new UIPropertyMetadata(0));
Unfortunately, with the code as written you will get the result shown in Figure 4 when you try to use the control by in the XAML for a Window.

Figure 4
Figure 4: Get the type of your default value correct, or else!

Of course, it is immediately apparent that the problem stems from the newly specified default value. The problem here is simply one of boxing and unboxing. The UIPropertyMetadata constructor boxes an Int32 and tries to unbox it back to a Double (because that is the type of the DP), resulting in instant catastrophe. The fix is as simple as changing to code to use the correct literal value:

new UIPropertyMetadata(0.0)
The good thing is that, as you can see from Figure 4, you’ll soon spot the problem if you forget to specify the correct default value.

A couple of additional considerations

Hopefully by now you’re thinking that DPs are fantastic and you should be using them in preference to standard .NET properties on all of your types. Or should you? There are a few things to really be aware of, though, which might be considered downsides of using DPs.

The first is that reading and writing a DP is a lot slower than reading and writing a standard .NET property. This probably comes as no real surprise, after all much more work is being done. Broadly speaking, this is not going to be a real issue unless you decide to read the value of a DP many, many times within a loop.

The more serious constraint is that the DependencyObject class derives from DispatcherObject, and DispatcherObject brings with it the notion of thread affinity. Attempting to update the value of a DP from a thread other than the one which created the object will result in an InvalidOperationException being thrown. This tends to mean that DPs should only be used on UI elements, or perhaps some types in a ViewModel that will be used as the targets of binding expressions.

Finally, with a .NET property your get{} and set{} accessors can do anything that you want them to. DPs offer a more constrained set of functionality, but they do allow you to add code to handle three specific situations.

Dealing with validation, coercion and property change

You have three things that you can optionally do when a value is set for a DP, which occur in the following order:
  1. The incoming value can be validated in a ValidateValueCallback handler
  2. The value can then be coerced in a CoerceValueCallback
  3. A PropertyChangedCallback will then fire, in which you can see both the old and new values
Let’s take a look at how the LoginControl might use this mechanism to handle changes to its MinPasswordStrength DP, which for the sake of this discussion comprises a notional value in the range of 0 (very weak) to 100 (super-strong).

Validation callbacks

The first callback that fires supports validation. You register a validation callback handler when you Register the property, passing in a reference to a static method as shown below:
public partial class
		LoginControl : UserControl
{
... = DependencyProperty.Register(...,
		new ValidateValueCallback(
			ValidateStrength ) );
	private static bool
		ValidateStrength( object obj )
	{
		double d = (double) obj;
		return d >= 0.0 && d <= 100.0;
	}
	...
}
The trick to validation is that you only receive the value that will be set for the property and that’s all.

This means that your validation code can’t query any properties on the object to which the property is being applied, and is thus normally limited to simple validation checks such as making sure that the value for the type is inherently sane.

Note that if you return false from the validation callback handler, WPF will generate and throw an ArgumentException on your behalf.

Coercion and property changed

Handling the coercion and property changed notifications requires you to specify some metadata for the property. This is typically done by passing a FrameworkPropertyMetadata object in to the Register() method, as shown below:
public partial class LoginControl :
	UserControl
{
	static LoginControl()
	{
		FrameworkPropertyMetadata metadata
	= new FrameworkPropertyMetadata(5.0,
	FrameworkPropertyMetadataOptions.None,
				new PropertyChangedCallback(
					StrengthChanged ),
				new CoerceValueCallback(
					CoerceStrength ) );
		... = DependencyProperty.Register(
	"MinPasswordStrength",typeof(double)
			, typeof(LoginControl), metadata,
			ValidateStrength );
	}
	...
	static void StrengthChanged(
		DependencyObject obj, 	
	DependencyPropertyChangedEventArgs e )
	{
		// e.NewValue is the new value for
		// the property
		// e.OldValue was the value for the
		// property
	LoginControl lc = (LoginControl) obj;
		CheckPasswordStrength(lc.Password);
	}
	static object CoerceStrength(
		DependencyObject obj, object value)
	{
	LoginControl lc = (LoginControl) obj;
		double d = (double) value;
		if( lc.CheckPasswordStrength )
			return d;
		return 0.0;
	}
	...
}
As you can see from the code, the coercion callback receives both the value that is being set and a reference to the DependencyObject itself. This enables it to use other properties on the element (in this case a Boolean that is used to indicate whether password strength should be checked or not; if this is false, then the value 0 is returned) to help it coerce the value. Similarly, the property changed notification event receives a reference to the DependencyObject and a change event argument type containing both the old and the new value.

‘So where does my value come from?’

Lots of work can ensue when you ask a DependencyObject for the value of a DP. The DP might be subject to a data binding expression, or currently be under the influence of an animation. WPF therefore processes the values of a DP through a pipeline as shown in Figure 5.

Figure 5
Figure 5: The DP processing pipeline

Obtaining the base value is itself interesting, as you can see that it can be obtained from one of eight different sources. These range, in order of priority from highest to lowest, from the value that has been set on the object using SetValue() through to the default value that is set when the property is registered. A local value will thus always override the value set in a style or trigger. Note also that inherited values from the element tree are in a lowly seventh place, thus ensuring that properties set in styles override those from an arbitrarily set parent element property.

One other interesting thing to note from Figure 5 is that when animating a property or resolving an expression, coercion occurs prior to validation. Yet when you explicitly set a property in your code using SetValue(), validation occurs before coercion.

With all this going on, it can be quite hard sometimes to work out where the value of a DP is coming from. You can use the DependencyPropertyHelper.GetValueSource() method to locate the originating value source (examine the BaseValueSource property on the returned ValueSource object) and also determine whether the property is an expression, is subject to animation or is being coerced.

Focus Pocus: Time for some magic with DPs

Now all the way back at the beginning of the article I mentioned that I would show you how to use and abuse DPs. We’re pretty much done on the using bit, so let’s get going on the abusing.

DPs provide a wonderful mechanism for extending the functionality of types without having to use inheritance. For example, consider the somewhat strange application shown in Figure 6.

Figure 6
Figure 6: Extending functionality without inheritance
The requirements are fairly simple: all I want to do is to display the content of the Button that has the focus in the TextBlock at the top of the Window that is currently showing “???”. The obvious solution is to trap the (Preview)GotFocus routed event at the Window level and use code in the event handler to do the work, which might look something like this:

private void Window_GotFocus( object
	sender, RoutedEventArgs e )
{ txtInfo.Text = (string)
	((ContentControl) e.Source).Content;
}
One downside of this approach is that the code that you’re writing is very specific; it’s not a general purpose technique that could be used for enabling or disabling controls based on the currently focused element, for example.

You could, of course, derive your own class from Window and add the necessary code there. Again, this approach has downsides, not the least of which is that you have to replicate this code if you want to add the same functionality to Grid, StackPanel, and so on.

So what we really need is a way for us to inject functionality into existing classes; and DPs, and in particular attached properties, let us do just that. To see how you might approach this, take a look at this code for the FocusPocus class:

// The GetXXX/SetXXX methods have been
// elided out of this class just to keep
// the code focused on the fun stuff
public class FocusPocus :
	DependencyObject
{
	// GetDoMagic() / SetDoMagic() elided
	...
	public static readonly
	DependencyProperty DoMagicProperty =
		DependencyProperty.
			RegisterAttached("DoMagic",
		typeof(bool), typeof(FocusPocus),
		new FrameworkPropertyMetadata(
			false, DoMagicChanged ) );
	static void DoMagicChanged(
		DependencyObject obj,
	DependencyPropertyChangedEventArgs e )
	{
		FrameworkElement ele = obj as
			FrameworkElement;
		if( ele != null ) {
			if( (bool) e.NewValue )
				ele.GotFocus += OnGotFocus;
			else
				ele.GotFocus -= OnGotFocus;
		}
	}
	static void OnGotFocus(object sender,
		RoutedEventArgs e) {
	SetFocusedElement((DependencyObject)
			sender, e.Source as
				IInputElement);
	}
	// GetFocusedElement()/
	// SetFocusElement() elided
	...
	public static readonly
		DependencyProperty
		FocusedElementProperty =
	DependencyProperty.RegisterAttached(
		"FocusedElement",
			typeof(IInputElement),
			typeof(FocusPocus),
		new FrameworkPropertyMetadata(null,
			FrameworkPropertyMetadataOptions.
			Inherits)
		);
}
As you can see, FocusPocus is a class with nothing more than two attached properties. Let’s look at each property in turn to see how it enables us to add the desired functionality to any container.

DoMagicProperty

DoMagic is a simple Boolean attached property. Its purpose in life is to enable us to add event handlers to elements to respond to the GotFocus event; and nothing more. You would use it as follows:
<Window xmlns="..." xmlns:x="..."
	xmlns:local="..."
	local:FocusPocus.DoMagic="true" />
If you cast your eyes back to the listing you’ll notice that when the value of the property is changed, an event handler for the GotFocus event is added (or removed if the value is set to false). So just by setting the property on the Window to true, FocusPocus’ OnGotFocus() method will be called whenever the focus is changed within the Window. As you can see, this does nothing other than set the second of the properties, FocusedElement, to hold a reference to the control which was the source of the event.

FocusedElementProperty

Again, FocusedElement is nothing special. It’s just another attached property that holds a reference to the control that last raised a GotFocus event. But here comes the (almost) clever bit. Notice that when the property was registered, I passed in the FrameworkPropertyMetadataOptions.Inherits flag as part of the metadata. This means that the value of this property is inherited through the element tree, which in turn means that I can read the value of this property on the TextBox itself.

This little trick lets us write this XAML:

<Window ... xmlns:local="..." />
	...
<TextBlock Text="{Binding RelativeSource=
		{RelativeSource Self},
			Path=(local:FocusPocus.
			FocusedElement).Content}" />
	...
</Window>
Unpicking the binding expression for the Text property reveals that the source object for the Binding is the TextBlock object itself (that’s what RelativeSource = {RelativeSource Self} means). As the FocusPocus.FocusedElement property supports inheritance, the binding will retrieve the reference that was stored in the OnGotFocus() event handler. Note that the brackets around the FocusPocus.FocusedElement in the binding are important, as this is how we refer to an attached property for the PropertyPath.

So what have we gained?

With this code in place the TextBlock always now shows the Content for the currently focused control. It does it without us having to write any event handlers in our Window class. It also means that the FocusPocus class can be used in any situation where we need to track the focused element from a parent container, whether it is a Window, Grid and so on. Finally, it enables us to use data binding to access the element, rather than procedural code.

This technique of injecting extra functionality, and in particular event handlers and inherited attached properties, can prove to be highly effective in reducing the number of times that you need to derive new classes.

Conclusion

In this article we have scratched the surface of WPF’s dependency property mechanism. There’s far more to it than can fit in a single article, including the ability to override metadata as needed, and to share ownership of DPs across multiple types. As you have hopefully seen, though, DPs offer a number of great benefits, particularly in the areas of data binding, animation and through property inheritance. What’s somewhat ironic is that we tend to hide DPs away behind ordinary .NET properties and then forget about them; a classic example of how encapsulation can improve our lives as we can gain all the benefits without having to worry about a whole new API.

Finally, it’s easy to think that DPs offer nothing more than a fancy property mechanism. However, one of their hidden powers is the ability to inject functionality into other types simply by using an attached property. This is an extremely useful technique that can help to avoid inheritance (remember, try to favour composition over inheritance) and allow us to produce cleaner and more easily testable code.


Dave Wheeler is a freelance consultant, who specialises in the various UI technologies within Microsoft .NET. He also writes and delivers courses for DevelopMentor, and speaks at various industry conferences including DevWeek and Software Architect. You can contact him at [email protected].

You might also like...

Comments

About the author

Dave Wheeler United Kingdom

Dave Wheeler is a freelance instructor and consultant who specialises in .NET application development. He’s a moderator on Microsoft’s ASP.NET and Silverlight forums and is a regular speaker at ...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Before software should be reusable, it should be usable.” - Ralph Johnson