附属物如何具有多重价值?

时间:2010-11-08 04:34:09

标签: wpf attached-properties

如何通过拥有父元素定义的单个属性 AttachedProperty ,通过该父元素的多个子元素设置多个值?

例如:

如果我有:

<DockPanel>
  <CheckBox DockPanel.Dock="Top">Hello</CheckBox>
  <CheckBox DockPanel.Dock="Bottom">World</CheckBox>
</DockPanel>

这里我们有一个DockPanel元素,它有一个Dock属性。如何将它同时设置为“顶部”然后“底部”?

3 个答案:

答案 0 :(得分:3)

最终会出现一个看起来像这样的方法

public class DockPanel : Panel
{
    public static readonly DependencyProperty DockProperty;
    // ...
    public static void SetDock(UIElement element, Dock dock)
    {
        element.SetValue(DockProperty, value);
    }
}

正如您所看到的,它实际上并未设置在父项上,而是设置在CheckBox本身上,通过DockPanel上的静态方法SetDock而不是父实例。在后面的代码中执行它会使这更清楚一点,注意我们从不使用DockPanel的实例。

DockPanel.SetDock(checkBox1, Dock.Top);
DockPanel.SetDock(checkBox2, Dock.Bottom);

希望这一点很清楚,除非你的问题是如何“引擎盖下”。在这种情况下,请参阅this问题。

从链接引用。

  

这种机制的目的是为了   “附加”到其他对象的信息   父对象需要的,而不是   孩子反对自己。

CheckBox不用于Dock属性,除非它在DockPanel中。 Grid.Row,Canvas.Left,Validation.HasError(只读)等也是如此。所以基本上,DockPanel是需要信息的人,但它需要所有的孩子才能存储它。因此,它正在使用附加属性。如果您创建了一个名为PuneetPanel的新面板,并且您需要一个Angel来计算子位置,那么您可以在此面板中定义自己的附加属性PuneetPanel.Angel,并且所有子节点都可以使用它而无需进行子类化。

答案 1 :(得分:0)

这是一个非常好的问题。答案在于AttchedProperty的工作原理。父级使用AttachedProperty来渲染子级。在渲染子项之前,父项查找在子项上定义的任何附加属性并应用于子项。

我在msdn中找到了这个可能对你有用的东西::

DockPanel定义了DockPanel.Dock附加属性,DockPanel将类级代码作为其渲染逻辑的一部分(具体来说,是MeasureOverride和ArrangeOverride)。
DockPanel实例将始终检查其任何直接子元素是否为DockPanel.Dock设置了值。如果是这样,那些值将成为应用于该特定子元素的呈现逻辑的输入....

您可以看到此链接以获取详细的概述::
http://http://msdn.microsoft.com/en-us/library/ms749011.aspx

希望它可以帮到你!!

答案 2 :(得分:0)

对于您自己的自定义附加属性,有两种方法可以实现您的目标:

1。如果可设置值的组合数量不复杂,则可以设置枚举类型为FlagsAttribute的附加属性。您可以使用按位或|

组合要设置的值
[Flags]
public enum MultiDock
{
  Left,
  Top,
  Right,
  Bottom
}

它在代码中的用法:

MyCustomPanelOrWhatever.SetMultiDock(MultiDock.Left | MultiDock.Bottom);

这有一个小问题,你不能直接在xaml中执行上述操作,你必须编写一个可以将字符串转换为标记的枚举值的MarkupExtension。它的用法如下:

<CheckBox src:MyCustomPanelOrWhatever.MulitDock="{src:FlaggedEnum Left|Bottom}"  />

2. 由于附加属性可以是任何类型,它们当然也可以是复杂类型(具有多个子属性)甚至是集合,因此很容易做到这样的事情: / p>

MyCustomPanelOrWhatever.SetMultiDock(new List<MultiDock> { MultiDock.Left, MultiDock.Bottom });

如果您已经通过这种方式定义了附加属性,则不需要任何xaml转换器,您可以直接使用它:

<CheckBox>
    <src:MyCustomPanelOrWhatever.MultiDock>
        <src:MultiDock.Left/>
        <src:MultiDock.Bottom/>
    </src:MyCustomPanelOrWhatever.MultiDock>
</CheckBox>