In my previous blog entry we examined the routed event system used by WPF. Similar to how routed events augment the standard .NET event-driven programming model, dependency properties take standard .NET properties to another level. In this entry we will discuss what dependency properties are and what advantages they bring to WPF development.
WPF leverages a property system which allows for much more sophisticated and intelligent usage of properties than was possible before. In addition to using regular CLR properties, the Windows Presentation Foundation also uses dependency properties. Dependency properties are used when the resolution of a property’s value is based on other properties or runtime settings (such as operating system settings).
Here are some important features of dependency properties:
Value resolution – DPs are used to form a system which can determine the actual property value based on various runtime information. The resolution process has an order of precedence it assigns to various environmental contexts in which the property might exist. For example, if the DP is being modified by an animation then the value supplied by the animation is the resolved value, but if it is not animated, then the value is derived from elsewhere.
Self-contained validation – DPs can have custom callback methods execute when the property value has changed. These callbacks can validate the new value or coerce the new property value into something acceptable, according to the semantics of the property.
Default values – DPs provide a consistent mechanism for associating a default value with a property. A DP’s default value has the lowest precedence in the value resolution process, meaning that if there is no other way to determine the property value, then the default value will be used.
Property metadata – The property system knows how a DP should behave based on metadata supplied at the time the property is registered with the system. Subclasses can tweak a DP by overriding the property’s metadata, instead of completely re-implementing the property itself. It is interesting to note that this metadata is not stored in attributes, partly because the performance impact associated with using reflection to manipulate the metadata was unacceptable.
XAML friendly – Just like normal properties, DPs can be set in XAML.
Value inheritance – Any DP can be given the ability to inherit its value from the property setting on an ancestor element, in the logical tree. This provides similar functionality to the ambient properties used in Windows Forms. Value inheritance is useful in many situations, such as propogating a data source down the element tree, font settings, flow direction (right-to-left) settings, etc.
Attached properties – A form of dependency property which allows a child element to store a value associated with a property defined on an ancestor element.
Dependency properties are used to support many features in WPF, and also many features can only be used in conjunction with dependency properties. For example, the data binding system in WPF is rooted in the FrameworkElement.DataContext dependency property. The value of that property is inherited by all descendant elements, meaning that all elements in a logical tree can implicitly share the same data source. On the other hand, only dependency properties on a framework element can be bound to the data source. WPF data binding utilizes and requires dependency properties. To learn more about data binding in WPF, read this article.
Using dependency properties is typically very straightforward because it is conventional for them to be wrapped by a normal CLR property. It is also possible to get and set the value of a DP via the DependencyObject.GetValue and DependencyObject.SetValue instance methods, respectively, but that is rarely necessary in most development scenarios.
It is also worth noting that a dependency property can only be created on a class which derives, directly or indirectly, from the System.Windows.DependencyObject class. That class is very high up in the WPF class hierarchy, which allows the majority of classes in WPF to leverage dependency properties.
The following resources can be used to learn more about dependency properties:
Demystifying dependency properties – A blog post which examines how the value of a dependency property is determined.
Further demystification of dependency properties – An example-based continuation of the post listed above.
Dependency Properties Overview – Microsoft’s explanation of dependency properties.
Overview of attached properties in WPF – A blog post which examines a special type of dependency property known as an “attached property.”
Attached Properties Overview – Microsoft’s explanation of attached properties.