Page view counter

Dependency Property System – Deeper Dive Part 1

On the 17th I began a discussion of Dependency Properties, but as I said then, there is more to say.  This central concept to Silverlight Programming has traditionally  been taught as an advanced concept.(Can we have  traditions in a product that hasn't really been released yet?) And to some degree, with good reason: you can pretty much ignore the Dependency Property System until/unless you're writing custom controls. Here are three reasons not to:

1. They're fascinating
2. They explain a lot about how things work
3. They are critical to creating your own custom controls

Okay, the real reason is #1; they're just interesting.

There are a couple ways to approach Dependency Properties. Most of us approach them practically, to accomplish a specific goal at first ("How do I wire up a DP in this custom control?") and then later, we return to understand the entire system into which they fit. It is the purpose of today's column to begin that second stage: examining the system as a whole.

An Adventure in Spelunking the Dependency Properties System

We need to start by acknowledging a few somewhat surprising facts:

The folks who created WPF and Silverlight made some rather radical (and I would argue technically courageous) decisions:

  • they said "the current properties are inadequate for our needs, and we're going to add a new layer on top that will not break the underlying layer but that will give us tremendous additional options." 
  • Thus, the Dependency Properties system is really a radical extension to the CLR and to that which is available in C++, Java, or even pre-WPF C#/VB.NET.  
  • Then the folks at Silverlight chose which parts of the system they would use, which they'd adapt and which they'd leave behind based on optimizing for the needs of Silverlight rather than just for pure isomorphic consistency.

Controversial but highly defensible decisions, and ones that will give us early headaches trying to understand all of it,  but long term benefits.

The biggest problem, of course, is that figuring out what is really going on can be a bit problematic, especially right now. This particular moment in history is a documentation purgatory.

  • The WPF books are excellent but not everything they say applies to Silverlight
  • The Beta2 chm file and help files are very good but now partially obsolete
  • The change document is helpful but not guaranteed to be complete
  • Full documentation of Dependency Properties was never a priority as it was considered somewhat advanced/obscure

So we're in for some fun.

To make this work, I'm going to need to (a) break this up into a few related posts and (b) try to impose some discipline on myself to do the set of DP posts within a relatively short period so I don't forget what I've covered already!   I'll tag them all with "Dependency Properties" so you can find them or skip them as you choose.

Quick Review of Why Dependency Properties were Added

As noted in my posting on the 17th the WPF designers quickly found that standard CLR properties were not responsive enough nor extensible enough to support declarative, animated and databound client-side applications. What was needed was a system that could establish the value of a property, at run time, based on input from a number of sources (e.g., the current value of other properties, rapidly changing animation values, etc.).

A key value of the Dependency Properties system was the ability to build properties that automatically notify any registered interested party each time the value of the property changes.  This free, painless and automatic implementation of the observer pattern is tremendously powerful and greatly reduces the burden on the client programmer (in fact, the data-binding system depends on it!).

[We cover the observer patten in detail in Programming .NET 3.5 – for an unauthorized excerpt, click here ]

That alone is worth the price of admission. It means that if you bind numerous controls to dependency properties, you are guaranteed to be notified any time the value of the property changes, without your writing a line of code. Whooah!

Cost - Benefit

 

I believe (and obviously the designers believed) there is enormous benefit to the Dependency Properties system, but let's not ignore the fact that you do pay a price, if only in learning this system.  In this posting I'll cover that price, in the next I'll start to explore some of the benefits.

The price, such as it is….

You need to learn, and grok, a new element in your class – Dependency Properties that interact with an underlying system that didn't usta'  exist. More, some of your properties are really just wrappers to these new DP's. What that means is that the backing value for some of your properties is not a member variable or a value in a database or a computation, but a Dependency Property.  That takes a little mind-share.

Here's what that looks like in code:

// clr wrapper
public bool Valuable
{
   get { return (bool) GetValue( ValuableProperty ); }
   set { SetValue( ValuableProperty, value ); }
}

A pretty standard get and set, except that you access your backing variable using GetValue and SetValue to get and set the value of a Dependency property named ValuableProperty (and that is the idiom, the CLR property name + the word Property = the name of the DP, thus Valuable + Property = ValuableProperty.

The declaration of the DP itself is much weirder,

public static readonly DependencyProperty ValuableProperty =
  DependencyProperty.Register(
  "Valuable",
  typeof( bool ),
  typeof( MyCustomControl ),
  new PropertyMetadata( new PropertyChangedCallback(   
      MyCustomControl.OnValuablePropertyChanged ) ) );

Let's  break this down. The first line declares my object (which is really a reference to a DependencyProperty) as public; it must be static and readonly, and its type is DependencyProperty and its name (identifier) is ValuableProperty.

We set that reference to what we'll get back by calling the static Register method on the DependencyProperty class. Register takes four arguments:

  1. The name of the dependency property wrapper
  2. The type of the DP being registered
  3. The type of the object registering it
  4. The Callback

The Callback is of type PropertyMetaData. You can imagine a world in which there are various pieces of MetaData for the DependencyProperty. At the moment, however, in Silverlight, there is only one: the callback.

The constructor for the PropertyMetaData takes an object of type PropertyChangedCallback which will be called any time the effective property value of the DP property changes.  We pass it a reference to the method to call (which equates to a callback).

The net of all of this is that we present to the world a CLR property (Valuable) which is in fact backed by a DependencyProperty which will call back to the method OnValuablePropertyChanged any time the effective value of the property changes.

The callback method will take two arguments:

  • A DependencyObject (the control)
  • An object of type DependencyPropertyChangedEventArgs

Typically you'll cast the first argument to be the type of the control that contains the property, and you'll cast the NewValue property of the DependencyPropertyChangedEventArgs object to the DependencyProperty that changed. You can then take whatever action you need to based on the change in the DP's value

[Listing updated 10/1 – 10:30 am]

   1: public class MyCustomControl : Control
   2: {
   3:  
   4:    public static  readonly DependencyProperty 
   5:       ValuableProperty = DependencyProperty.Register(
   6:        "Valuable",
   7:        typeof( bool ),
   8:        typeof( MyCustomControl ),
   9:        new PropertyMetadata( new PropertyChangedCallback( MyCustomControl.OnValuablePropertyChanged ) ) );
  10:  
  11:    public bool Valuable
  12:    { 
  13:       get { return (bool) GetValue( ValuableProperty );}
  14:       set { setValue( ValuableProperty, value );}
  15:    }
  16:  
  17:    private static void OnValuablePropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
  18:    {
  19:       MyCustomControl control = d as MyCustomControl;
  20:       bool b = (bool) e.NewValue;
  21:    }
  22: }
  23:  

 

 

That's pretty much it, except getting your head around why you did all this; and for that we have to begin to explore, in more detail, the benefits of the system. That is, once you have this, what have you gained?

Stay tuned, rather than gloss over it, I'd like to take the time to explore it in depth.

-jesse

Published 30 September 2008 01:07 PM by jesseliberty

Comments

# obsid said on 30 September, 2008 08:03 PM

You didnt mention the default value of a DP though.  I believe this is fairly new (just in RC0 or recently) so even people that have used DP's before may not have realized it.

# GA30 said on 30 September, 2008 09:04 PM

really? default values are now supported in RC0? is this the case?

# Dew Drop – September 30, 2008 (Evening Edition) | Alvin Ashcraft's Morning Dew said on 30 September, 2008 10:28 PM

Pingback from  Dew Drop – September 30, 2008 (Evening Edition) | Alvin Ashcraft's Morning Dew

# 22khz said on 01 October, 2008 02:41 AM

I think line 6: Valuable v = (Valuable) e.NewValue; is actually bool v = (bool)e.NewValue because the method is static and can't reference object dependencyproperty.

Am I right?

# 2008 October 01 - Links for today « My (almost) Daily Links said on 01 October, 2008 03:57 AM

Pingback from  2008 October 01 - Links for today « My (almost) Daily Links

# Silverlight news for October 1, 2008 said on 01 October, 2008 04:58 AM

Pingback from  Silverlight news for October 1, 2008

# Community Blogs said on 01 October, 2008 09:54 AM

In this post: Mike Snow, Bill Reiss, Jesse Liberty, Harsh Bardhan, Tim Heuer, Matthias Shapiro, and Jeff

# jesseliberty said on 01 October, 2008 10:28 AM

22khz you are 100% correct. In fact, the listing is just wrong. It should be as I've updated it.

Thanks!

# obsid said on 01 October, 2008 11:59 AM

I believe if you look at the PropertyMetadata object in reflector you will see it has these constructors now:

   public PropertyMetadata();

   public PropertyMetadata(object defaultValue);

   public PropertyMetadata(PropertyChangedCallback propertyChangedCallback);

   public PropertyMetadata(object defaultValue, PropertyChangedCallback propertyChangedCallback);

   public PropertyMetadata(object defaultValue, PropertyChangedCallback propertyChangedCallback, CoerceValueCallback coerceValueCallback);

The microsoft docs at msdn.microsoft.com/.../system.windows.propertymetadata_members(VS.95).aspx havent been updated yet I think.

# Silverlight news for October 2, 2008 said on 02 October, 2008 02:04 AM

Pingback from  Silverlight news for October 2, 2008

# Jesse Liberty - Silverlight Geek said on 09 October, 2008 09:47 AM

Over the past month I've posted half a dozen min-articles about creating custom controls that can interact

# Microsoft Weblogs said on 09 October, 2008 10:10 AM

Over the past month I've posted half a dozen min-articles about creating custom controls that can interact

# Mirrored Blogs said on 09 October, 2008 10:37 AM

Over the past month I've posted half a dozen min-articles about creating custom controls that can

# Custom Controls - the handling at Blog von J??rgen Ebner said on 10 October, 2008 06:15 AM

Pingback from  Custom Controls - the handling at Blog von J??rgen Ebner

# Jesse Liberty - Silverlight Geek said on 23 October, 2008 11:21 AM

We have, I think, officially passed the point where anyone can keep up with the new technology available

# Microsoft Weblogs said on 23 October, 2008 11:51 AM

We have, I think, officially passed the point where anyone can keep up with the new technology available

# Silverlight Tipps vom Insider said on 24 October, 2008 05:08 AM

Pingback from  Silverlight Tipps vom Insider

# ManishBharti said on 05 December, 2008 12:56 AM

Hi I need a full sample for this to really sink it in my head. Send me some link which has demonstrated this through custom controls example.

# Jesse Liberty - Silverlight Geek said on 05 December, 2008 03:01 PM

    I have completed the four part video series Creating Skinnable Customer Controls and I

# Microsoft Weblogs said on 05 December, 2008 03:52 PM

    I have completed the four part video series Creating Skinnable Customer Controls and I

# Erstellen von anpassbaren Custom Control at Programming with Silverlight, WPF & .NET said on 08 December, 2008 04:07 PM

Pingback from  Erstellen von anpassbaren Custom Control at Programming with Silverlight, WPF & .NET

# Jesse Liberty - Silverlight Geek said on 22 December, 2008 05:34 PM

When we started creating How Do I videos, the idea was to have stand alone videos that do not depend

# Microsoft Weblogs said on 22 December, 2008 06:17 PM

When we started creating How Do I videos, the idea was to have stand alone videos that do not depend

# Templates & Custum Controls at Programming with Silverlight, WPF & .NET said on 23 December, 2008 08:30 AM

Pingback from  Templates & Custum Controls at Programming with Silverlight, WPF & .NET

# Templates & Custum Controls at Programming with Silverlight, WPF & .NET said on 23 December, 2008 08:32 AM

Pingback from  Templates & Custum Controls at Programming with Silverlight, WPF & .NET

# Using Dependency Property and DataBinding in WPF « Code Blitz said on 11 March, 2009 08:51 PM

Pingback from  Using Dependency Property and DataBinding in WPF « Code Blitz

# Jesse Liberty - Silverlight Geek said on 29 May, 2009 04:57 PM

    I had the pleasure of presenting What’s New In Silverlight 3 both at TechEd this year and

# Microsoft Weblogs said on 29 May, 2009 05:42 PM

I had the pleasure of presenting What’s New In Silverlight 3 both at TechEd this year and then again

# Programming with Silverlight, WPF & .NET » Was ist neu in Silverlight 3 said on 05 June, 2009 06:26 AM

Pingback from  Programming with Silverlight, WPF & .NET » Was ist neu in Silverlight 3

# Top-silverlight » Blog Archive » What???s New In Silverlight 3 said on 06 June, 2009 07:46 AM

Pingback from  Top-silverlight  » Blog Archive   » What???s New In Silverlight 3