Sunday, February 6, 2011

Dependency Properties

Somewhat bewildered on my first encounter with this property, I started on a small journey to discover it and hence putting down my findings below for future reference as well as if it helps anyone.

Dependency Property Overview
Primarily to support the functionalities in WPF and Silverlight, designers at Microsoft invented something called as Dependency properties.

In regular .NET code, when you create a property, you typically back it by a private field in the containing class and by defining its getter and setter.
Dependency property is used very much like a normal property but differs significantly in the way it is implemented to support its additional features like
a. Setting via data binding, style, theme;
b. Change Notification;
c. ValidateValueCallBack: Callback to accept or reject new values and returns a Boolean
d. CoerceValueCallback: Can change new values into something more acceptable
The value of the property is determined using certain well-defined values precedence rules.(explained below)
Basic principle of the dependency property - it's an object oriented property i.e. and hence you need to define it within a class. But it can't be any class. It needs to inherit the methods needed to work with a dependency property and this means it has to inherit from DependencyObject or one of its descendants.
(C# only supports single inheritance, so it is important that you choose the correct class to inherit from if you also want properties and methods of a particular control.)
public class MyClass:DependencyObject
{
public static readonly DependencyProperty MyDPProperty =
DependencyProperty.Register("MyDP",typeof(double), typeof(MyClass));
}
And we can't just create an instance of DependencyProperty. The framework needs to know about it to allow it to take part in the common behaviors and hence the solution employed by its designers is to use a static method of Dependency property to create an instance and register it:
public static readonly DependencyProperty MyDPProperty =
DependencyProperty.Register("MyDP",typeof(double),typeof(MyClass));

The DependencyProperty object above is set up to store a value of type double, with name MyDP and to act as a property belonging to MyClass.

This is how all dependency properties are created and they have to be public static readonly fields. The reason is that the property belongs to the class and it’s the implementation that sorts out the instance being used. That is there is only one property object shared among all of the instances of the class that uses it.

There are a number of overloaded Register methods but at the very least you have to specify:-
• the name of the property as a string "MyDP" in the example
• the type of the property typeof(double) in the example
• the type of the class the property belongs to typeof(MyClass) in the example.

Two ways of referring to the property either by its name i.e. MyDP or by the variable MyDPProperty. You can also register a range of metadata values and callbacks but this is the minimum you need to create a custom dependency property.

Value precedence
Dependency properties obtain their value from a variety of inputs. What follows is the order the Silverlight property system uses when assigning the runtime values of dependency properties, with the highest precedence listed first:
a. Animations: If an animation is currently running, and that animation is changing the property value, Silverlight uses the animated value.
b. Local value: If you've explicitly set a value in XAML or in code, Silverlight uses the local value. If you set a property using a resource or data binding, it's considered to be a locally set value.
c. Styles: Silverlight styles allow you to configure multiple controls with one rule. If you've set a style that applies to this control, it comes into play now.
d. Property value inheritance: Silverlight uses property value inheritance with a small set of control properties, including Foreground, FontFamily, FontSize, FontStretch, FontStyle, and FontWeight. That means if you set these properties in a higher level container (like a Button or a ContentControl), they cascade down to the contained content elements (like the TextBlock that actually holds the text inside).
e. Default value: If no other property setter is at work, the dependency property gets its default value. The default value is set with the PropertyMetadata object when the dependency property is first created.

One of the advantages of this system is that it's very economical. For example, if the value of a property has not been set locally, Silverlight will retrieve its value from the template or a style. In this case, no additional memory is required to store the value. Another advantage is that different property providers may override one another, but they don't overwrite each other. For example, if you set a local value and then trigger an animation, the animation temporarily takes control.

References
Couple of resources where you can get decent information on the subject:
1. Pro WPF in Vb 2010: Chapter 4 Dependency Properties
2. http://www.i-programmer.info/programming/wpf-workings/443-inside-dependency-properties-.html - A useful link explaining the subject in a very easy manner (and much of what I have stated below is from this link)

No comments:

Post a Comment