Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependency property value is not inherited

I declared a dependency property with FrameworkPropertyMetadataOptions.Inherits:

public static class DesignerItemStyles {
    public static readonly DependencyProperty HeaderBackgroundProperty = 
        DependencyProperty.RegisterAttached(
            "HeaderBackground", typeof(Brush), typeof(DesignerItemStyles),
            new FrameworkPropertyMetadata(
                Brushes.DesignerViewElementHeaderBackground,
                FrameworkPropertyMetadataOptions.Inherits));

    /* Below are Get & Set as usual */
}

It kind of works, but somehow not throughout the visual tree. Here is a screenshot showing ContentPresenter that inherit value from HeaderedDesignerItemChrome: Node that inherits value

And now, a screenshot showing content of the ContentPresenter, and it does not inherit the value. Nor it is set to something else - it is a default value: Direct child that does not

Any idea why?

like image 805
Eugene Strizhok Avatar asked Mar 19 '14 19:03

Eugene Strizhok


2 Answers

Using this is not that straight forward since there are some rules that need to be followed to implement property with inheritable values. Here they are:

On parent, dependency property must be defined as attached property. You can still declare property getter/setter, but property must be attached. Here is simple declaration:

public static readonly DependencyProperty InheritedValueProperty =
   DependencyProperty.RegisterAttached("InheritedValue",
   typeof(int), typeof(MyClass), new FrameworkPropertyMetadata(0, 
   FrameworkPropertyMetadataOptions.Inherits));
public static int GetInheritedValue(DependencyObject target)
{
   return (int)target.GetValue(InheritedValueProperty);
}
public static void SetInheritedValue(DependencyObject target, int value)
{
   target.SetValue(InheritedValueProperty, value);
}
public int InheritedValue
{
   get
   {
      return GetTimeSlotDuration(this);
   }
   set
   {
      SetTimeSlotDuration(this, value);
   }
}

Child objects would define their instance of the property with inherited value using AddOwner. Following is the code that goes into say MyChildClass sample class:

public static readonly DependencyProperty InheritedValueProperty;
public int InheritedValue
{
   get
   {
      return (int)GetValue(InheritedValueProperty);
   }
   set
   {
      SetValue(InheritedValueProperty, value);
   }
}
static MyChildClass()
{
   InheritedValueProperty = 
       MyClass.InheritedValueProperty.AddOwner(typeof(MyChildClass),
           new FrameworkPropertyMetadata(0,
                   FrameworkPropertyMetadataOptions.Inherits));
}

The global default value is preserved and inheritance still works, if the single argument overload is used...

MyClass.InheritedValueProperty.AddOwner(typeof(MyChildClass));

Note that property is in child class declared as standard dependency property and that it specifies Inherit in meta-data options.

With setup like this now when MyChildClass in parented to MyClass visually or logically they will share the same property value automatically.

So technically, what you see in the Visual Tree is doing what you told it to do. It set the default value that you told it to and the inherited controls inherit from the value of the parent which is your ContentPresenter

like image 142
123 456 789 0 Avatar answered Sep 24 '22 03:09

123 456 789 0


Eliminating one of the two ContentPresenters (visible on both screenshots just above DesignerItemsPresenter) worked for me. I am inclined to believe that was a bug in WPF framework itself.

like image 22
Eugene Strizhok Avatar answered Sep 22 '22 03:09

Eugene Strizhok