views:

177

answers:

2

I'm not quite sure if I've got the right grasp on this or not, what I've read seems to agree with what I'm trying to do, however It doesn't seem to be working.

If I add an additional owner to a dependency property of a class, whenever the orig class dp changes, the change should get propagated to the additional owner, correct?

What I have is a custom control, which I want to set a property on, and then on certain objects that are within the custom control data template inherit this property value.

public class Class1: DependencyObject{
  public static readonly DependencyProperty LongDayHeadersProperty;

  public bool LongDayHeaders {
     get { return (bool)GetValue(LongDayHeadersProperty); }
     set { SetValue(LongDayHeadersProperty, value); }
  }

  static Class1(){
    LongDayHeadersProperty = DependencyProperty.Register("LongDayHeaders", typeof(bool), typeof(Class1),
            new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
  }
}

public class Class2: DependecyObject{
  public static readonly DependencyProperty LongDayHeadersProperty;

  public bool LongDayHeaders{
    get{ return(bool)GetValue(LongDayHeadersProperty); }
    set{ SetValue(LongDayHeadersProperty, value); }
  }

  static Class2(){
    LongDayHeadersProperty = Class1.LongDayHeadersProperty.AddOwner(typeof(Class2));
  }
}

But if I assign a DependencyPropertyDescriptor to both properties, it only fires for the Class1 and Class2 doesn't change.

Have I missed something in my understanding?

UPDATE

After some testing, I'm not even sure if my child control is considered a child control within the logical or visual tree. I think it is, but the lack of success leads me to believe otherwise.

There a many class2's which exist in an observable collection of class1. This, to me, makes them childs of class1? But even if I use RegisterAttach on class2, and set the property in class1, it doesn't seem to have any effect?

A: 

As MSDN states, the Inherits flag only works when you use RegisterAttached to create the property. You can still use the property syntax for the property.

Update

For clarity, here is how I would define the properties:

public class Class1 : FrameworkElement
{
    public static readonly DependencyProperty LongDayHeadersProperty = 
        DependencyProperty.RegisterAttached("LongDayHeaders", 
        typeof(bool),
        typeof(Class1),
        new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));

    public bool LongDayHeaders 
    {
        get { return (bool)GetValue(LongDayHeadersProperty); }
        set { SetValue(LongDayHeadersProperty, value); }
    }
}

public class Class2: FrameworkElement
{
    public static readonly DependencyProperty LongDayHeadersProperty = 
        Class1.LongDayHeadersProperty.AddOwner(typeof(Class2));

    public bool LongDayHeaders
    {
        get{ return(bool)GetValue(LongDayHeadersProperty); }
        set{ SetValue(LongDayHeadersProperty, value); }
    }
}

If you want your children to be logical children of your control, you need to call the AddLogicalChild. Also, you should expose them through the LogicalChildren property. I must also point out that both classes must derive from FrameworkElement or FrameworkContentElement, as the logical tree is only defined for these elements.

Since you are using an ObservableCollection, you would handle the collection changed events and Add/Remove the children depending on the change. Also, the LogicalChildren property can just return your collection's enumerator.

Abe Heidebrecht
RegisterAttached makes the property of class 2, applyable on class 1.so:<local:class1 class2.LongDayHeaders="False" />But i just want to go <local:class1 LongDayHeaders="False" />
Psytronic
that shorthand is not possible
Rob Fonseca-Ensor
A: 

You are confusing DependencyProperties with Attached (Dependency) Properties.

A DP is for when a class wants bindable, stylable etc properties on itself. Just like .NET properties, they are scoped within their classes. You can register for a property changed event on individual objects, but not globally. TextBox.Text is an example of this. Note that Label.Text is unrelated to TextBox.Text.

An AP is for when a class wants to decorate another object with additional properties. The class that declares the AP is able to listen for property changed events on ALL instances of other objects that have this AP set. Canvas.Left is an example of this. Note that you always have to qualify this setter: <Label Text="Hi" Canvas.Left="50"/>

Rob Fonseca-Ensor