none
Why Dependency Properties? RRS feed

  • Question

  • I've been working with WPF for a while now, studying it, programming with it, blogging about it, etc.  Despite all that, there is something which fundamentally bothers and eludes me.  I just don't feel comfortable with dependency properties.  I've read a lot about them, but none of the explanations have satisfied my curiosity.  I'm hoping that someone might explain a few things to me, please...

    - How do DPs work?  What is actually involved with the inner workings of a DP?  What happens when you set a DP?  What happens when you get the value of one?  Is this explained/documented anywhere?  I've read about the precedence rules used during value resolution, but how exactly does that work?

    - How does the value inheritance of DPs work?  When do inherited values get propogated down the visual tree, and when do they not? 

    - Why must the target of a binding be a DP, but the source needn't be a DP? 

    - What would WPF be like without DPs? 

    I know that most of these questions can be answered by digging through the framework code in Reflector, but I'd rather have someone from the WPF team just explain it in plain English.  Once I understand DPs in more depth I'll feel much more comfortable with WPF in general. 

    Anyone care to enlighten me? :)

    Wednesday, November 15, 2006 3:33 AM

Answers

  • A lot of the motivation was to support features that WPF advertises as being key features, without necessarily touting the WPF property system as a feature in and of itself.

    The post about expressions being important is correct. The expressions are necessary to provide a property value deferral mechanisms for two WPF features: asynchronous databinding (so won't hold up the UI thread) and dynamic resources. The reason for asychronous databinding is pretty obvious. The dynamic resource concept is useful in and of itself, but also supports at least two other more clearly recognizable features: allowing styles to be created that incorporate dynamic participants such as information that comes from the current active theme on the system, and enables hooks to styles such that style elements might come from shared, changeable resources that the user might be changing during app lifetime. A complex control such as GridView can use this technique to break up how its styles are exposed for customization.

    But wait there's more!

    Dependency properties hold metadata. For the most part, app writers don't need to care about the metadata. But the metadata carries information that's important to processes like the layout system. Several of the bits in the metadata are dedicated for having the property report whether a change in it would impact layout.

    There are some nice XAML-for-UI-definition features that rely on the property being a dependency property, mostly these are in the Style/Template space. The property you use for a Trigger (or a Condition in a MultiTrigger) must be a dependency property. The property you set with a Setter must be a dependency property. A DP was a need here because of the property-change notification that a DP has natively, and to support DynamicResource usages there.

    Dependency properties are handy for properties that hold determined values (like values that might be influenced by the entire input system but resolve to a single state), because of the callbacks that are part of the property metadata. That's the "dependency" part of dependency property.

    The specific questions:

    - How do DPs work?  Ummm, I'm going to skip that one for now. This is already a long enough post. But it's a good topic idea for the SDK, adding it to my list. I could give a short or even mediumsize answer, but if you've already read the existing SDK topics you'd find that answer unsatisfying.

    - How does the value inheritance of DPs work? Actually, the property value inheritance is exclusively through the logical tree. There are of course logical/visual tree intersects where you'd see inherited values appearing. Most of the behavior you see is built in to FrameworkElement. There's a specific piece of it that's built into the default implementation of its OnPropertyChanged implementation, whereby a change to a DP that has Inherits in the metadata will call a helper that walks the tree and invalidates that property on all logical child elements such that each of them has to ask the property system for the value again. Inherited property values always get propagated down the tree by that helper; it's just a question of whether that value is the one that wins according to property value precedence (you've read the topic on DP precedence?) Exception: you can adjust the inheritance a little to create 'separated trees', for example you don't want to default inherit into a tree that might be sourced from a Frame.

    - Why must the target of a binding be a DP, but the source needn't be a DP?  Target has to be a DP because of the need for expression support. The source needn't because it's not a necessary or realistic restriction. Binding to a CLR object directly (without even using a DataSource) is a big scenario. There was still a need for many binding scenarios to have the source notify the binding engine of changes to the source value, which conceivably could be addressed by DPs, but that was more easily addressed by introducing the INotifyPropertyChanged interface. With an interface, you can add source changed notifications to any open class. Note also that INotifyPropertyChanged is in System.ComponentModel and not in the WPF DLLs, it's intended for a wider audience. With a DP, you're restricted to deriving from DependencyObject.

    - What would WPF be like without DPs?  Uhhh it would probably be even MORE complicated. I'll grant you that DPs/the property system is complex. But at least that complexity is somewhat centralized. If you have the need to understand DPs in greater detail, once you gain that knowledge, you'll be able to apply it to understanding quite a few of the other features of WPF.

    Wednesday, November 15, 2006 11:46 PM

All replies

  • Josh-

    Thanks for the request...I'll see if we can get one of the brains behind DPs to address those questions...

    One thing for sure, we'd prefer that most "App" authors shouldn't need to know about DPs.
    Component authors need to go there...but not "App" authors.

    At least that is our goal.

    Thanks, Rob

    Rob Relyea
    Program Manager, WPF Team
    http://rrelyea.spaces.live.com

     

    Wednesday, November 15, 2006 2:00 PM
    Moderator
  • WPF Architecture
    http://msdn2.microsoft.com/en-us/library/ms750441.aspx

    Dependency Properties
    http://msdn2.microsoft.com/en-us/library/ms753192.aspx

    There is expression concept behind dependency properties.
    For example: x = a + b
    when a or b changed x also updates.
    Expressions widely used in 3D software: Houdini, Maya.
    Expressions could be complex and i waiting next WPF version, where expressions will be in open API :)

    The problem i see in WPF that DPs are not supported by language.
    Good area for research :)


    Wednesday, November 15, 2006 2:55 PM
  • Rob,

    > Thanks for the request...I'll see if we can get one of the brains behind DPs to address those questions...

    That would be excellent and extremely helpful.  Thanks!

    > One thing for sure, we'd prefer that most "App" authors shouldn't need to know about DPs.
    > Component authors need to go there...but not "App" authors.

    I agree that app developers shouldn't have to know how DPs work.  That's a good goal. 

    Thanks again!  I'm looking forward to the answer...

    Wednesday, November 15, 2006 3:01 PM
  • Ivan,

    Thanks for the links, but I've already read all of that.  I'm looking for a deeper understanding of the topic than those help files provide.

    Wednesday, November 15, 2006 3:04 PM
  • I have to admit that the WPF's DP system is pretty complex, I am just trying to figure out things like the value resolution precedence, DP value changed callback and coerce value call back, DP metadata, and stuff like that, because those things are very important when authoring custom controls

    Sheva
    Wednesday, November 15, 2006 3:31 PM
  • A lot of the motivation was to support features that WPF advertises as being key features, without necessarily touting the WPF property system as a feature in and of itself.

    The post about expressions being important is correct. The expressions are necessary to provide a property value deferral mechanisms for two WPF features: asynchronous databinding (so won't hold up the UI thread) and dynamic resources. The reason for asychronous databinding is pretty obvious. The dynamic resource concept is useful in and of itself, but also supports at least two other more clearly recognizable features: allowing styles to be created that incorporate dynamic participants such as information that comes from the current active theme on the system, and enables hooks to styles such that style elements might come from shared, changeable resources that the user might be changing during app lifetime. A complex control such as GridView can use this technique to break up how its styles are exposed for customization.

    But wait there's more!

    Dependency properties hold metadata. For the most part, app writers don't need to care about the metadata. But the metadata carries information that's important to processes like the layout system. Several of the bits in the metadata are dedicated for having the property report whether a change in it would impact layout.

    There are some nice XAML-for-UI-definition features that rely on the property being a dependency property, mostly these are in the Style/Template space. The property you use for a Trigger (or a Condition in a MultiTrigger) must be a dependency property. The property you set with a Setter must be a dependency property. A DP was a need here because of the property-change notification that a DP has natively, and to support DynamicResource usages there.

    Dependency properties are handy for properties that hold determined values (like values that might be influenced by the entire input system but resolve to a single state), because of the callbacks that are part of the property metadata. That's the "dependency" part of dependency property.

    The specific questions:

    - How do DPs work?  Ummm, I'm going to skip that one for now. This is already a long enough post. But it's a good topic idea for the SDK, adding it to my list. I could give a short or even mediumsize answer, but if you've already read the existing SDK topics you'd find that answer unsatisfying.

    - How does the value inheritance of DPs work? Actually, the property value inheritance is exclusively through the logical tree. There are of course logical/visual tree intersects where you'd see inherited values appearing. Most of the behavior you see is built in to FrameworkElement. There's a specific piece of it that's built into the default implementation of its OnPropertyChanged implementation, whereby a change to a DP that has Inherits in the metadata will call a helper that walks the tree and invalidates that property on all logical child elements such that each of them has to ask the property system for the value again. Inherited property values always get propagated down the tree by that helper; it's just a question of whether that value is the one that wins according to property value precedence (you've read the topic on DP precedence?) Exception: you can adjust the inheritance a little to create 'separated trees', for example you don't want to default inherit into a tree that might be sourced from a Frame.

    - Why must the target of a binding be a DP, but the source needn't be a DP?  Target has to be a DP because of the need for expression support. The source needn't because it's not a necessary or realistic restriction. Binding to a CLR object directly (without even using a DataSource) is a big scenario. There was still a need for many binding scenarios to have the source notify the binding engine of changes to the source value, which conceivably could be addressed by DPs, but that was more easily addressed by introducing the INotifyPropertyChanged interface. With an interface, you can add source changed notifications to any open class. Note also that INotifyPropertyChanged is in System.ComponentModel and not in the WPF DLLs, it's intended for a wider audience. With a DP, you're restricted to deriving from DependencyObject.

    - What would WPF be like without DPs?  Uhhh it would probably be even MORE complicated. I'll grant you that DPs/the property system is complex. But at least that complexity is somewhat centralized. If you have the need to understand DPs in greater detail, once you gain that knowledge, you'll be able to apply it to understanding quite a few of the other features of WPF.

    Wednesday, November 15, 2006 11:46 PM
  • Wow! 

    Thank you very much, Wolf.  I'll have to read your post several times before it all sinks in, but that is really really helpful.  Much appreciated!! :)

    Thursday, November 16, 2006 12:57 AM
  • Hi, Wolf, your post is awesome, but I have an additional question on DP, it seems that the DP system treats all property values as reference type(aka System.Object), I think this will imply a performance problem, you know, WPF has to deal with some many types which are not reference types, for instance Double, Point, Point3D, Rect, and other enum types, all those types are value types, whenever i retrieve values of value type from the DP store or set values of value type to the DP store, an unboxing and boxing operations will immediately follow, which IMHO is not performant, so my question is why WPF team doesn't have generic dependency property idea in mind when designing the DP system, and what kind of design or architectural decision you guys made?

    Sheva
    Thursday, November 16, 2006 12:07 PM
  • I would suggest people interested in DependencyProperties as well as any basic part of WPF a good read of Charles Petzold's last book: Applications = Code + Markup. It cannot be clearer about how they work and how to use them.

    Marc Lacoursiere, RooSoft Computing

    Thursday, November 16, 2006 9:07 PM
  •  Zhou Yong wrote:
    Hi, Wolf, your post is awesome, but I have an additional question on DP, it seems that the DP system treats all property values as reference type(aka System.Object), I think this will imply a performance problem, you know, WPF has to deal with some many types which are not reference types, for instance Double, Point, Point3D, Rect, and other enum types, all those types are value types, whenever i retrieve values of value type from the DP store or set values of value type to the DP store, an unboxing and boxing operations will immediately follow, which IMHO is not performant, so my question is why WPF team doesn't have generic dependency property idea in mind when designing the DP system, and what kind of design or architectural decision you guys made?

    Sheva

    I could answer that for you from a previous post I read. Basically a lot of WPF was complete before .Net 2.0 was complete (and hence there was no generics support). There was a decision to be made. Go back and rework the framework to take advantage of generics, or mark it as a "next release" work item. After weighing the pros and cons, it was decided that reworking the framework with generics support wouldn't be as effective use of the project resources as getting in other features. So you'll see a number of cases where Generics are taken advantage of (ObservableCollection<T> for instance) but the framework will use it and spit out non-generics.

     

    Friday, November 17, 2006 12:10 AM
    Moderator
  • Generics: see http://blogs.msdn.com/nickkramer/archive/2005/08/30/457783.aspx

    BTW if you're looking for the DP expert, Nick meets that qualification far more than I do. Nick's now working on WPF/E.

    Friday, November 17, 2006 3:01 AM