2009-07-23 113 views
21

对于附加属性如何将其值传递给父元素或子元素,我感到有些迷惑。 TextElement.FontFamily会导致子元素继承分配给该属性的值(看似下游操作,父对子)。 Grid.Column导致父项在特定位置显示该子项(看似上游操作,子对父母)。附加属性值如何知道是向上还是向下?我对这个错误的看法是错误的吗?还是有一个错误会将所有这些置于透视之中?附加属性在WPF中的工作原理是什么?

<StackPanel TextElement.FontFamily="Wingdings"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="*"/> 
      <ColumnDefinition Width="*"/> 
     </Grid.ColumnDefinitions> 

     <Button Grid.Column="1" Content="My Button"/> 
    </Grid> 
</StackPanel> 

回答

38

这里有两个概念:依赖项属性附加依赖​​项属性。 “附加属性”是依赖属性,支持依赖关系property value inheritance

关于基本依赖属性,一个非常粗略的说法是,它们基本上是从wpf(逻辑/视觉)树中的父元素继承它们的值。如果它的metadata设置为FrameworkPropertyMetadataOptions,则依赖项属性(附加或不附加)将继承其值“向下”。 继承标志,并且在很多情况下都是如此。

附加属性是可以通过DependencyObject.SetValue方法在任何wpf对象上设置的属性(基本上,至少为 DependencyObject)。此机制的目的是“附加”到父对象所需的其他对象信息,而不是子对象本身。例如,Grid.Row是网格所需的附加属性,用于将项目放置在其渲染区域中。

相关属性由wpf对象系统自动“向下”继承。

附加属性在特定对象的代码中显式检查“向上”。在网格的情况下,在确定将物品放置在何处时,它会检查每个包含物品的Grid.Row和Grid.Column附加属性的值。

它也常常是创建自定义附加属性的技术,它以某种方式修改它们所连接的对象(例如,Drag'n'Drop functionality via attached properties)。

作为附加说明,继承附加属性的一个很好的示例是TextElement.FontFamily。 Grid.Row和Grid.Column属性没有设置Inherits标志。

TextElement.FontFamily,从反射器:

FontFamilyProperty = DependencyProperty.RegisterAttached("FontFamily", typeof(FontFamily), typeof(TextElement), new FrameworkPropertyMetadata(SystemFonts.MessageFontFamily, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure), new ValidateValueCallback(TextElement.IsValidFontFamily)); 

Grid.Row,从反射器:

RowProperty = DependencyProperty.RegisterAttached("Row", typeof(int), typeof(Grid), new FrameworkPropertyMetadata(0, new PropertyChangedCallback(Grid.OnCellAttachedPropertyChanged)), new ValidateValueCallback(Grid.IsIntValueNotNegative)); 
+1

有趣且信息丰富。但是,这种情况如何:2x2网格(A)包含2x2网格(B)。网格B包含一个按钮。如果网格B具有网格。列附加属性设置为1(因此它出现在其父网格的第二列中,网格A),不应该将附加属性向下级联到网格B的按钮,因此按钮会出现在网格B的第二列? – Pwninstein 2009-07-23 23:01:23

2

MSDN

虽然附加属性是任何对象上可设置的,这并不必然意味着设置属性将产生实际的结果,或者该值永远不会被其他对象使用。通常,附加属性的目的是使来自各种可能的类层次结构或逻辑关系的对象都可以将公共信息报告给定义附加属性的类型。定义附加属性的类型通常遵循这些模型之一:

  • 定义附着 属性被设计成使得它可以 是元素 ,将用于设置的值的父元素的类型附 财产。该类型然后通过内部逻辑 针对某个对象树结构迭代其 子对象, 获取值并以某种方式对这些值执行操作。

  • 限定附 属性的类型将被用作用于各种可能 父元素和内容模型的子 元件。

  • 定义所附 属性的类型表示服务。其他 类型为附加的 属性设置值。然后,当 设置属性的元素将在服务的 上下文中进行评估时,附加的 属性值将通过服务类的内部逻辑 获取。

An的实施例父定义的附加属性

最典型的方案,其中WPF定义附加属性是当父元素支持的子元素集合,并且还实现了一个行为,其中行为的具体情况将分别为每个子元素进行报告。

DockPanel定义了DockPanel.Dock附加属性,而DockPanel具有类级代码作为其渲染逻辑(特别是MeasureOverride和ArrangeOverride)的一部分。一个DockPanel实例会一直检查它的任何直接子元素是否为DockPanel.Dock设置了一个值。如果是这样,则这些值将成为应用于该特定子元素的呈现逻辑的输入。嵌套的DockPanel实例每个处理它们自己的直接子元素集合,但是这种行为是DockPanel处理DockPanel.Dock值的具体实现。从理论上讲,可能会有影响超出直接父级元素的附加属性。如果DockPanel。Dock附加属性设置在一个没有DockPanel父元素的元素上,不会引发错误或异常。这仅仅意味着设置了一个全局属性值,但它没有可能消耗信息的当前DockPanel父项。

0

简单地说这是我的理解它(请纠正我,如果我错了)。

对象(A)实现一个属性,该属性将附加到另一个对象(B)(对象B甚至不知道这个“可附加”属性的存在)。对象B需要从DependencyObject继承。

对象A还实现了静态方法来检查它在其他对象中的“可附加”属性A.GetAttachedProperty(B)。

如果B具有来自A的附加属性,则A.GetAttachedProperty将读取并返回其值。否则A将尝试读取它,并返回null,因为它不在那里。

相关问题