依赖/附加属性如何在内部工作以及值存储在何处?

时间:2013-08-12 14:54:57

标签: wpf dependency-properties attached-properties

我对这些魔法有点不清楚。 据我所知,依赖属性从DependencyObject继承,因此存储了值:

  • 在实例中如果赋值(在本地字典中)
  • 如果未指定值,则从指向父元素的链接中获取。

    protected object GetValue(string propertyName)
    {
       if (LocalValues.ContainsKey(propertyName))
       {
          return LocalValues[propertyName];
       }
       return Parent.GetValue(propertyName);
    }
    

    我对此是否正确?

我也不明白存储附加属性的值在哪里?

Control.FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
typeof(Control), new FrameworkPropertyMetadata(SystemFonts.MessageFontSize,
FrameworkPropertyMetadataOptions.Inherits));

对Attached属性的AddOwner方法调用是否为实例字段赋值?这是什么时候发生的?价值在哪里?

谢谢!

2 个答案:

答案 0 :(得分:3)

WPF中的属性系统非常复杂。 MSDN确实有很多信息,但通常很难找到。 While there are many ways a DependencyProperty can be set,我不确定您是否需要关注存储值的位置。

对于本地值,您可以假设它存储在DependencyObject上(同样您不应该关心它存储在何处),但需要注意的是它们不是基于字符串存储的。它确实与DependencyProperty的实例相关联。这就是您希望将属性添加到属性的原因。如果有人在您的控件上设置TextElement.FontSize,就像设置您的本地FontSize属性一样。

就从父级继承属性的值而言,此与附加属性一起发生。来自FrameworkPropertyMetadataOptions的{​​{3}}:

  

虽然属性值继承似乎有效   非附加依赖项属性,a的继承行为   通过运行时中的某些元素边界的非附加属性   树未定义。始终使用RegisterAttached来注册属性   您可以在元数据中指定Inherits。

答案 1 :(得分:3)

依赖项属性的值存储在我们应用属性值的对象(派生自DependencyObject)中。

让我们以你的TextElement.FontSizeProperty附加属性为例:

<StackPanel TextElement.FontSize="20" ... >
  ...
</StackPanel>

XAML解析器将其转换为以下内容:

...
TextElement.SetFontSize(stackPanel, 20);
...

内部:

public static void SetFontSize(DependencyObject element, double value)
{
  element.SetValue(TextElement.FontSizeProperty, value);
}

因此,在stackPanel对象上设置TextElement.FontSize与调用

相同
stackPanel.SetValue(TextElement.FontSizeProperty, value)

SetValue()是DependencyObject类中定义的方法。在方法内部发生了许多复杂的事情,但最终,依赖属性的有效值被包装在一个名为EffectiveValueEntry的结构中,并存储在DependencyObject内的以下实例字段中:

private EffectiveValueEntry[] _effectiveValues;