如何通过拥有父元素定义的单个属性 AttachedProperty ,通过该父元素的多个子元素设置多个值?
例如:
如果我有:
<DockPanel>
<CheckBox DockPanel.Dock="Top">Hello</CheckBox>
<CheckBox DockPanel.Dock="Bottom">World</CheckBox>
</DockPanel>
这里我们有一个DockPanel元素,它有一个Dock属性。如何将它同时设置为“顶部”然后“底部”?
答案 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>