views:

502

answers:

3

This is how I register a DependencyProperty:

    public static readonly DependencyProperty UserProperty = 
        DependencyProperty.Register("User", typeof (User), 
             typeof (NewOnlineUserNotifier));                                                                                                                 


    public User User
    {
        get
        {
            return (User)GetValue(UserProperty);
        }
        set
        {
            SetValue(UserProperty, value);
        }
    }

The third parameter of the DependencyProperty.Register method requires you to specify the type of the Control where the Dependency Property resides in (in this case, my User Control is called NewOnlineUserNotifier).

My question is, why do you actually specify the type of the owner, and what happens if you specify a different type than the actual owner's ?

+3  A: 

The type that you call the Register method from is not the de facto owner of the property, therefore you can't specify a different type than the actual owner since the type you specify is the actual owner.

An example where this may be useful is when you create a custom control that contains other controls. Previously with WinForms if you had some extra information that was only useful to that container, but semantically belonged to the child, then the best you could do was place that information in the hold-all "Tag" property. This both removed type safety and you were never sure that another class wouldn't try and store something else in the tag. Now with WPF dependency properties allow you to tie values to objects without the object itself needing to hold the value. A trivial example:

public class ButtonContainer : Control
{
    public Button ChildButton { get; set; }

    public static readonly DependencyProperty FirstOwnerProperty =
    DependencyProperty.Register("FirstOwner", typeof(ButtonContainer),
         typeof(Button));

    public ButtonContainer()
    {
        ChildButton = new Button();
        ChildButton.SetValue(FirstOwnerProperty, this);
    }

}

Now the button has an extra property that only makes sense within the context of the ButtonContainer and can only be accessed within the context of the ButtonContainer - like a typesafe, encapsulated Tag.

Using the new class as follows:

ButtonContainer container1 = new ButtonContainer();

ButtonContainer container2 = new ButtonContainer();
container2.ChildButton = container1.ChildButton;

As the ChildButton is moved from one container to another the value of its FirstOwnerProperty travels with it as though it was a real member of the Button class. Container2 can call ChildButton.GetValue(FirstOwnerProperty) and find out which ButtonContainer originally created the button (why it might want to do this is left as an exercise for the reader...). All of this is possible without the need to subclass the button to a narrow speciality.

Martin Harris
+1  A: 

This is because the same DependencyProperty can be defined differently (with different metadata) for several types

Thomas Levesque
+1  A: 

In a nutshell, when you're registering a DP, you're adding an object(DP) to a list attached to a class(owner). This operation only "lives" in the class where it is declared and often is not related to it.

Sergey Aldoukhov