【发布时间】:2011-05-20 22:19:02
【问题描述】:
如何从数据模板中设置父/祖先控件的属性?
我能想到的唯一方法是在我的表单上创建一个虚拟的不可见控件,然后使用转换器、onewaytosource 和 relativesource findancestor 绑定将其中一个属性与正确的默认值绑定,这是一个非常糟糕的解决方案。
我想要做的是能够让 setter 以不同的控件为目标,就像使用绑定到不同的源一样。
【问题讨论】:
如何从数据模板中设置父/祖先控件的属性?
我能想到的唯一方法是在我的表单上创建一个虚拟的不可见控件,然后使用转换器、onewaytosource 和 relativesource findancestor 绑定将其中一个属性与正确的默认值绑定,这是一个非常糟糕的解决方案。
我想要做的是能够让 setter 以不同的控件为目标,就像使用绑定到不同的源一样。
【问题讨论】:
几个可能的选项: 1)在DataTemplate内部的绑定上,使用ElementName将源设置为父级,并使用OneWayToSource进行绑定。这会将值从绑定目标(DataTemplate 中的元素)传输到绑定源(父控件) 2) 使用 DataTemplate 和控件都绑定到的公共对象。 DataTemplate 将使用 OneWayToSource 绑定到它,控件将使用 OneWay 绑定到它。它甚至可以是一种资源,因此您可以从 XAML 访问它。 3) 使用RelativeSource 和FindAncestor。 4)使用某种路由事件,并在控制级别处理它。它将通过附加的行为从数据模板中触发(google it!)。事件将传递数据,事件处理程序将在控件上设置相关属性。
选项 1,3 与您的建议类似。选项 2、4 不同。在优雅方面,我更喜欢选项2。
此外 - 请注意所有解决方案中的冲突。如果 DataTemplate 在单个控件内多次实例化,则所有实例都将尝试设置控件的属性。效果将是最后一次执行的集合尝试的效果,如果您无法控制它们的顺序,在某些情况下可能会出现问题。
亚历克斯。
【讨论】:
假设您的祖先在数据模板内部,您可以使用“名称”属性为该祖先命名。一旦有了名称,您就可以使用 setter 的“TargetName”来指定该祖先。
例子:
<DataTemplate>
<Grid Name="ControlGrid">
<Path x:Name="Arrow" Fill="Black">
<Path.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Visibility" TargetName="ControlGrid" Value="Collapsed"/>
</Trigger>
</Path.Triggers>
</Path>
</Grid>
</DataTemplate>
【讨论】: