I'm writing this article in response to a newsgroup posting where the reader states:

I am confused by this concept : why it is designed like this? Is there any document on it's design purpose and intention? The document in Avalon CTP is not helpful.

I'm sure a lot of people either are, or will be, wondering the same things, so I figured I would whip together this article for future reference.


The DependencyObject/ DependencyProperty design actually exists for several reasons all of which I'll ultimately touch on within this article, but let's start with one of the main concepts for which this design exists known as "attached properties". You'll encounter the concept of attached properties almost immediately as you start to use Avalon. Attached properties are dependency properties that other classes declare that can then be applied to any class you will ever throw into the Avalon mix. Let's look at one of the simplest examples of attached properties which involves positioning an item on a Canvas. Canvas has four dependency properties regarding positioning: TopProperty, BottomProperty, LeftProperty and RightProperty. Now, let's say we want to just throw a random UI element onto a Canvas. That UI element's class has no prior knowledge of the existence of the Canvas class or how it chooses to position the elements it contains. Therefore, when I want to put that UI element "into" a Canvas, I need to decorate it with Canvas specific dependency properties to get it to lay out correctly.

Right about now you're probably thinking "Well why not just have base class for all UI elements with Top, Bottom, Left and Right properties?". Well the answer to that is simple if you consider a different layout container such as the Grid. The Grid doesn't just layout things at a certain static X,Y coordinate like the Canvas. It uses rows and columns and automagically positions contained elements based on all the contents of the columns (for X) and rows (for Y). So, to accomplish this, the Grid offers the following dependency properties for positioning instead1: ColumnProperty and RowProperty.

So the next question is: How do these properties get applied to arbitrary classes? Well first off, the classes obviously need to be DependencyObject subclasses. From the consumer point of view, DependencyObject is little more than a glorified Hashtable2. It's job is to store the current values of any DependencyProperty that is ever applied to it. Setting a dependency property is simple:

// Create a button
Button myButton = new Button();

// Button ultimately derives from DependencyObject, so let's set 
// some properties so that it can be positioned on a Canvas!
myButton.SetValue(Canvas.TopProperty, new Length(100, UnitType.Pixel));
myButton.SetValue(Canvas.LeftProperty, new Length(100, UnitType.Pixel));

// Add the button to a canvas and it will be positioned at 100,100
myCanvas.Children.Add(myButton);

Actually, you know what? That's the long winded version because Microsoft has defined a well-known pattern for manipulating attched properties that make it a little easier for us. The pattern basically says that the class that owns the dependency property should provide static accessor methods to get/set the value on arbitrary DependencyObject instances. So let's look at that version:

Button myButton = new Button();

Canvas.SetTop(myButton, new Length(100, UnitType.Pixel));
Canvas.SetLeft(myButton, new Length(100, UnitType.Pixel));

myCanvas.Children.Add(myButton);

Hmmm... wait, that's a long winded version too!!! Why write any C# at all? Let's see how this pans out in XAML!

<Canvas ID="myCanvas" xmlns="http://schemas.microsoft.com/2003/xaml">
  <Button ID="myButton" Canvas.Top="100" Canvas.Left="100"/>
</Canvas>

Remember that pattern I just mentioned? Well XAML relies on it and translates the Canvas.Top attribute syntax to a Canvas.SetTop call.

Ok, this all seems simple enough now that we've been introduced to it right? So, what's the big deal? Well, wait... we've only scratched the surface with the introduction of attached properties. Attached properties aren't the only place that dependency properties should be used. I just decided to started with them because they demonstrate one of the key features that DependencyObject enables, which is the ability to tack infinite amounts of data onto existing objects without them ever having to know about it in the first place. So, let's look at a simpler scenario for dependency properties now, the Canvas.HeightProperty. This could have easily been designed as a plain vanilla .NET instance property of type Length on the Canvas class and nobody else will ever apply this property to anything but a Canvas, so why go through the trouble of making it a dependency property? Point of fact, it still does appear as an instance property on the Cavas class, but the reason it's defined as a dependency property is simple: to gain generic support from Avalon in terms of services. The "big deal" once you use dependency properties is that Avalon can also offer many services to your DependencyObject subclasses now without having to know about their custom implementation details (in this case Canvas.Height ). Perhaps the easiest service to demonstrate, which is probably also the most prominent in Avalon, is animation. Any dependency property can be animated. Let's take that sample we've been working with and animate the attached property a little bit:

<Canvas ID="myCanvas" xmlns="http://schemas.microsoft.com/2003/xaml">
  <Button ID="myButton" Canvas.Left="100">
    <Canvas.Top>
      <LengthAnimation From="0" To="100" Duration="2"
         RepeatDuration="Indefinite" AutoReverse="True"/> 
    </Canvas.Top>
  </Button>
</Canvas>

This will animate the button up and down from 0 to 100 (pixels) over a two second period. Now admittedly, I probably wouldn't want to animate the position of a Button in the real world, but that's actually the point that I'm driving at. This could just as easily be a Rectangle or another Canvas or even my own custom control! The positioning of the element on the Canvas and animation of it's properties is done exactly the same way for any DependencyObject subclass that is ever written from now until eternity.

Ok, ok... I can hear the masses screamning: "Bah! Animation, who needs it!?". Fine, fine... what about the rest of these services that are based on dependency properties then?

Service Description
Default
Values
Provides abillity to set the default value for anyone who uses a particular dependency property in one location (see PropertyMetaData.DefaultValue)
Expressions Provide the ability to base a dependency property on a calculated value instead of a constant (those familiar with IE's CSS expression support already have a head start on this one). Perhaps the coolest part of expressions is that you can write your own calculation logic quite easily by simply deriving from Expression
Databinding Actually implemented as an Expression, provides the ability to bind data from various sources to our property values.
Inheritance For those familiar with CSS, this is the cascading aspect of something like a font style being applied to the of your HTML document applying to all descendant elements without explicit font style declarations of their own
Styling A Style in Avalon is basically3 a declaration of a set of dependency property values
Property
Invalidation
Avalon strongly encourages the concept of dependency property caching for performance reasons4, property invalidation is the act of notifying the caching class that it's local, cached version is no longer valid

So, that's it! Hopefully this article helps you to understand the necessary level complexity that is introduced by the DependencyObject/DependencyProperty model. Without DependencyObject/DependencyProperty, the only way to achevie the same type of generic behavior in .NET would be through something like reflection which we all know has serious performance side-effects. The design enables infinite levels of extensibility and provides powerful services for your custom classes which allow other developers to use them in ways that you may never have even imagined.

1 Grid is more complex than this, but for purposes of this example this is all that is needed to undersand.
2 In actuality, the design of DependencyObject is more complex with great consideration for performance.
3 A style can actually get quite a bit more advanced when it defines a VisualTree
4 For more on cached properties, check out this section of the SDK

posted on Saturday, December 04, 2004 8:41 AM |

Comments

# DependencyObject and DependencyProperty in Avalon
Posted by Stuart Celarier on 12/6/2004 6:58 AM
Drew Marsh has a nice article on the DependencyObject&nbsp;and DependencyProperty design in Avalon.
# re: Avalon: Understanding DependencyObject and DependencyProperty
Posted by John Davis on 12/6/2004 7:36 AM
All this Avalon stuff sure looks a lot like DirectAnimation rehashed.
# re: Avalon: Understanding DependencyObject and DependencyProperty
Posted by Drew Marsh on 12/6/2004 9:10 AM
John,

That's because it basically is. ;) That plus tons of MSHTML and SVG features.
# Architettura Avalon
Posted by Ricciolo on 12/6/2004 2:33 PM
# re: Avalon: Understanding DependencyObject and DependencyProperty
Posted by Ifeanyi Echeruo on 12/7/2004 10:07 AM
I once heard Zhanbo Sun, a tester for the dependency property system, give the best and most concise definition for the dependency system. Its a value computation engine.

The fact that it stores values is just on of many ways it computes value. Animation, inheritance and databinding being some of the other means.

Getting an attached property (Canvas.GetLeft(obj)) is like computing the value of a property by looking up a hashtable with obj as the key

Invalidation takes place when computation ^dependencies^ (are lights coming on now?) change.

Its also the reason why caching is good. You never really know how expensive the computation (GetValueBase) is going to be so cache the current computed value until it's invalid.
# DependencyObject and DependencyProperty in Avalon
Posted by Stuart Celarier on 12/12/2004 8:37 PM
Drew Marsh has a nice article on the DependencyObject&nbsp;and DependencyProperty design in Avalon.Update:...
# re: Avalon: Understanding DependencyObject and DependencyProperty
Posted by Hierogli on 2/21/2005 8:37 AM
Hi,

it seems a runtime-binding technology with its every drawbacks/benefits.
Focusing on drawbacks, I think the performance is almost the most important viewpoint in UI. As a developer, I think this is a 'cool feature', but the avalon designer team missed the point: they make the Avalon developer-friendly, not user-friendly.
# Investigating WinFX: DependencyObject / DependencyProperty
Posted by TheChaseMan's Frenetic SoapBox on 10/7/2005 6:11 PM
# A Collection of useful Avalon tutorial
Posted by digitalnetbizz's WebLog on 11/6/2005 12:55 AM
While researching for information about Avalon, I realized&nbsp;that I'm always going back to the same...
# Tutoriales de WPF
Posted by Haaron Gonzalez on 11/6/2005 9:25 AM
# Tutoriales de WPF
Posted by Haaron Gonzalez on 11/6/2005 9:46 AM
# Tutoriales de Windows Presentation Foundation
Posted by Haaron Gonzalez Weblog on 11/6/2005 10:04 AM
# Dependency Property Notes
Posted by Community Blogs on 7/27/2006 7:58 PM
I've run into dependency properties in both Windows Presentation Foundation and Windows Workflow Foundation.
# Dependency Property?
Posted by Nam, Seungho's Blog on 9/12/2006 5:44 AM
http://blog.hackedbrain.com/articles/UnderstandingDependencyObjectAndDependencyProperty.aspx
# A Collection of useful Avalon tutorial
Posted by digitalnetbizz's WebLog on 1/11/2007 7:23 PM
While researching for information about Avalon [ for play-n-learn sample app ], I realized that I'm always
# re: Avalon: Understanding DependencyObject and DependencyProperty
Posted by crish on 3/1/2006 11:18 PM
Hi,

The article on DependencyProperties is very useful. Iam dealing with a scenario where Iam want to use DependencyProperty within a usercontrol, such that triggers can be used to activate storyboards within XAML based on these properties.

My sample code looks like this:
public partial class MyControl : UserControl .....

private static DependencyProperty HasTextProperty = DependencyProperty.Register( "HasText", typeof(bool), typeof(MyControl), new FrameworkPropertyMetadata(false)); public bool HasText { get { return txtDisplay.Text.Length > 0;}}

Iam getting a error while trying to implement it...
{"Error at element 'Trigger' in markup file 'ControlTest;component/mycontrol.xaml' : 'HasText' string is not a valid value for 'Property' property of type 'DependencyProperty'.."}

Do let me know how can i deal with this error?

Thanks in advance..
# re: Avalon: Understanding DependencyObject and DependencyProperty
Posted by DarkByte on 5/21/2005 9:05 AM
Hierogli,

I believe that you missed the point. Avalon is the presentation part of the system. Making it user-friendly is going to be the task of designers and programmers, because, what has to be user-friendly, if not the user interfaces that are created !

Actually, to me, Avalon is the perfect concept. You see, i've been in the field of computers (technical, programming, etc etc) for a long time, but there is one thing i do not have. I have no sense of art. I cannot design a nice looking app. Of course, its going to be very functional, user aware, etc etc .. but will look plain flat and ugly. Now with Avalon, i can have a friend that has that artistical sense, play with the interface, try new designs and i know that all the coding behind it will not need to be done again and again and again. Talk about the fantasmagorical feeling i can get from that.

One thing i'd like to know, how do i define a DependencyProperty for a collection, i mean, if i have a collection of MyObject which could be a semi complex object (say, 1 int and 1 float), and i want the property to be coming from a string. A bit like a polyline reads its coordinates. I guess my getter should create object and parse the string itself, right ?
Comments have been closed on this topic.