0

I'm trying to implement value inheritance for a DependencyProperty in a custom WPF DependencyObject and I'm faling badly :(

What I want to do:

I have two classes T1 and T2 that have both a DependencyProperty IntTest, defaulting to 0. T1 should be the root to T2, just like a Window is the logical root/parent to a TextBox it contains.

So when I don't set the value of T2.IntTest explictly it should provide the value of T1.IntTest (just like for example TextBox.FlowDirection usually delivers the parent window's FlowDirection).

What I did:

I created two classes T1 and T2, deriving from FrameworkElement in order to use FrameworkPropertyMetadata with FrameworkPropertyMetadataOptions.Inherits. Also I read that in order to use value inheritance you must design the DependencyProperty as an AttachedProperty.

Currently when I assign a value to the root T1, it is not returned by the DP-Getter of the child T2.

What am I doing wrong???

These are the two classes:

// Root class
public class T1 : FrameworkElement
{
    // Definition of an Attached Dependency Property 
    public static readonly DependencyProperty IntTestProperty = DependencyProperty.RegisterAttached("IntTest", typeof(int), typeof(T1), 
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.Inherits));

    // Static getter for Attached Property
    public static int GetIntTest(DependencyObject target)
    {
        return (int)target.GetValue(IntTestProperty);
    }

    // Static setter for Attached Property
    public static void SetIntTest(DependencyObject target, int value)
    {
        target.SetValue(IntTestProperty, value);
    }

    // CLR Property Wrapper
    public int IntTest
    {
        get {  return GetIntTest(this); }
        set { SetIntTest(this, value); }
    }
}


// Child class - should inherit the DependenyProperty value of the root class
public class T2 : FrameworkElement
{
    public static readonly DependencyProperty IntTestProperty = T1.IntTestProperty.AddOwner(typeof(T2),
        new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.Inherits));

    public int IntTest
    {
        get { return (int)GetValue(IntTestProperty); }
        set { SetValue(IntTestProperty, value); }
    }
}

And here is the code to try it out:

        T1 t1 = new T1();
        T2 t2 = new T2();

        // Set the DependencyProperty of the root
        t1.IntTest = 123;

        // Do I have to build a logical tree here? If yes, how?

        // Since the DependencyProperty of the child was not set explicitly, 
        // it should provide the value of the base class, i.e. 123. 
        // But this does not work: i remains 0   :((
        int i = t2.IntTest;    
Knasterbax
  • 7,895
  • 1
  • 29
  • 23

1 Answers1

0

The key attribute of an attached property is that it can be (usually is) declared on an object different than the one it is being set on. In this case you've declared everything you needed on T1 but you should have stopped there (get rid of the IntTest property wrapper though - AP uses the Get/Set methods instead). You could have also declared IntTest on some other helper class. Wherever you declare it you can set it on any DependencyObject.

// set on the declaring type
T1.SetIntTest(t1, 123);
// set on your other type
T1.SetIntTest(t2, 456);
// set on any other framework type
Button button = new Button();
T1.SetIntTest(button, 789);

The other part you seem to be struggling with is setting up your tree. Inheritance works as part of the logical hierarchy so in order to inherit a value from another instance the inheriting object needs to be a logical child of the originating object. Since you've derived from the base FrameworkElement you're not getting any of the benefits of containment afforded by ContentControl and ItemsControl which have the concept of children (single and multiple respectively) built in.

John Bowen
  • 24,213
  • 4
  • 58
  • 56