WPF FAQ
Get Microsoft Silverlight
Skip Navigation Links

Dependency Properties

In order to store data in a class you need a place to put it. Traditionally, classes encapsulate data in the form of member fields that are part of the data structure of the class. Whenever we create an instance of a class we have a physical address for the fields of that class. This means ultimately that classes create memory pressure because of their physical size. Now consider the situation in which we have millions of objects instantiated, each of which have properties and fields which all take up memory. It is very possible that a large roportion of the objects have a default state which will never change throughout the life of the application. The fields storing such data may be wasting many megabytes of otherwise useful memory.

 A well known pattern which addresses the problems of memory hogging data storage for object graphs that hold many millions of items is the Flyweight pattern. This well known design enables an object to hold data only when it needs to, usually by storing the data in some kind of dictionary or hashtable. In this pattern the cost of creating the storage space, which may be a CPU pressure is outweighed by the savings in memory when a large number of objects gold varying amounts of data.

The reason for the dependency object in WPF is because, unlike previous graphical systems where it was wise to minimise the number of stored graphical objects, WPF uses thousands or millions of lightweight objects to provide very complex graphical representations. The logical tree of objects that we create in XAML is mirrored and expanded upon in the visual tree so that a simple representation of a dialog box or window is backed by a plethora of retained-mode graphical objects. The potential for memory pressure is therefore very great.

What is declared by an object as a dependency property is in fact nothing more than an identifier. This static "property" is really a key which associates an object with a specific storage identifier. For example graphical objects have a Background property that can be set explicitly or through the use of templates or styles..

A dependency property has the advantage of being virtual unless actually used. For example, they have default values which are used unless the value has been explicitly set or "coerced". The advantage of this is again a question of memory pressure. The static declaration defines the default value once and is constant. All objects that use the property without explicitly setting the values use the defaults. A good example of this is the Transform settings of an object. In XAML we can declare that an object has a transform but this does nothing more than provide the virtual or potential storage space for the property. If we don't change it explicitly then the default value, a unitiy transform that basically does nothing, is used. The object however could be changed later by, say, an animation, which will modify the value of the property.

The actual value of a dependency property as seen by the object may be set by many sources. The origins of these values come from the complex interactions of the WPF system and have a strict order of precedence. Essentially, there are no less than eleven ways that a dependency property might be modified. They are listed here from the lowest to the highest priority.

11. Default value. This is declared in the dependency property and is used in the case that no other value has been applied.

10. Inherited values. A property might inherit a value from a parent element. An example of this is the DataContext which is inherited unless specifically set.

9. Default style, set by a theme. Border and text styles for buttons or text boxes will use a theme style.

8. Style setters. Styles contained by the, page, application or animations use setters to modify the value of a dependency property.

7. Template triggers. A property may be set by a template depending upon a MouseOver or Focused state for example.

6. Style triggers. Similarly, styles can specify triggers that apply styles according to the value of a property. Maybe a bank balance value would be shown in red if the account was overdrawn.

5. Implicit Styles. These styles are defined in the resources of the object or page that uses them and override default styles which are of lower precedence.

4. TemplatedParent template properties. Dependency properties which are owned by items in the visual tree and which exist because they have been created as the result of a template setting are modified using this principle. You will not declare anything explicitly for this but rather it is inferred by the action of the template system.

3. Local value. Explicitly set by markup or a SetValue call in code.

2. Animations. Properties set by animation storyboard setters.

1. Coersion. This is the highest priority exception case which is to allow you to alter the value of a property despite every other attempt. Some properties are coerced automatically but in general, you will have to respond to a callback and set the value in code to override all the other possibilities. Basically, coersion is a get out clause in which you can say "I don't care what you think. Do it my way!" To do this you'll use a CoerceValueCallback.