依赖属性和附加属性是如何在内部工作的?值存储在哪里?

6

我有点不太清楚这些魔法。从我的理解来说,依赖属性是从DependencyObject继承的,因此值被存储在那里:

  • in the instance itself if value is assigned (in the local dictionary)
  • or taken from the link to a parent element if value is not specified.

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

    Am I correct in this?

我不理解附加属性的值存储在哪里?
Control.FontSizeProperty = TextElement.FontSizeProperty.AddOwner(
typeof(Control), new FrameworkPropertyMetadata(SystemFonts.MessageFontSize,
FrameworkPropertyMetadataOptions.Inherits));

AddOwner 方法调用附加属性时会将值分配给实例字段吗?这是何时发生的,值去哪里了?

谢谢!

2个回答

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;

2
WPF中的属性系统相当复杂。MSDN上有很多信息,但通常很难找到。虽然有很多方法可以设置DependencyProperty,但我不确定您需要关心值存储在哪里。对于本地值,您可以假定它存储在DependencyObject上(再次强调,您不应该关心它存储在哪里),但要注意它们不是基于字符串存储的。它确实与DependencyProperty的一个实例相关联。这就是为什么您会想要向属性添加所有者的原因。如果有人在您的控件上设置了TextElement.FontSize,那么它就像设置了您的本地FontSize属性一样。
关于从父级继承属性值,这仅适用于附加属性。从FrameworkPropertyMetadataOptionsMSDN entry中可以看到:

虽然非附加依赖属性的属性值继承可能会起作用,但是在运行时树中通过某些元素边界继承非附加属性的继承行为是未定义的。请始终使用RegisterAttached来注册属性,在元数据中指定Inherits。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接