CellTemplate 中的 DataTrigger 绑定到 HeaderTemplate;可以吗?
这里的目标是在标题复选框发生变化时检查所有网格复选框:
<Window.Resources>
<Style TargetType="CheckBox" x:Key="InnerBox">
<Setter Property="HorizontalAlignment" Value="Center" />
<Style.Triggers>
<DataTrigger Value="True"
Binding="{Binding IsChecked,
ElementName=HeaderCheckbox}">
<Setter Property="IsChecked" Value="True" />
</DataTrigger>
<DataTrigger Value="False"
Binding="{Binding IsChecked,
ElementName=HeaderCheckbox}">
<Setter Property="IsChecked" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<DataGrid>
<DataGrid.Columns>
<!-- col1 -->
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<!-- header check -->
<CheckBox Name="HeaderCheckbox" />
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!-- body check -->
<CheckBox Style="{StaticResource InnerBox}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- col2 -->
<DataGridTextColumn Binding="{Binding}" Header="Text" />
</DataGrid.Columns>
<!-- sample data -->
<sys:String>1</sys:String>
<sys:String>2</sys:String>
<sys:String>3</sys:String>
</DataGrid>
看起来像:
由于某种原因,触发器不着火。
有什么想法吗?
The goal here would be to check all grid checkboxes if the header checkbox changes:
<Window.Resources>
<Style TargetType="CheckBox" x:Key="InnerBox">
<Setter Property="HorizontalAlignment" Value="Center" />
<Style.Triggers>
<DataTrigger Value="True"
Binding="{Binding IsChecked,
ElementName=HeaderCheckbox}">
<Setter Property="IsChecked" Value="True" />
</DataTrigger>
<DataTrigger Value="False"
Binding="{Binding IsChecked,
ElementName=HeaderCheckbox}">
<Setter Property="IsChecked" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<DataGrid>
<DataGrid.Columns>
<!-- col1 -->
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<!-- header check -->
<CheckBox Name="HeaderCheckbox" />
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<!-- body check -->
<CheckBox Style="{StaticResource InnerBox}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- col2 -->
<DataGridTextColumn Binding="{Binding}" Header="Text" />
</DataGrid.Columns>
<!-- sample data -->
<sys:String>1</sys:String>
<sys:String>2</sys:String>
<sys:String>3</sys:String>
</DataGrid>
Looks like:
For some reason, the trigger does not fire.
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如您所注意到的,
DataTemplate
内的ElementName
绑定无法到达模板外部的元素。这是因为它可以多次实例化,并且具有自己的名称范围,因此您在DataTemplate
内创建的任何ElementName
绑定都将在模板内查找具有该名称的另一个元素。使用 Snoop 查看它,我们还可以看到
RelativeSource
绑定不能直接使用,因为它们位于可视化树的不同部分我能想到的解决此问题的唯一方法是将两个复选框绑定到一个共同的祖先,例如父
DataGrid
和使用附加属性或标签
属性。示例和
ElementName
binding inside aDataTemplate
can't reach an element outside of the template as you noticed. This is because it can be instantiated many times and has its own namescope so anyElementName
binding you create inside aDataTemplate
will look inside the template for another element with that name.Looking at it with Snoop we can also see that a
RelativeSource
binding can't be used directly since they are in different parts of the Visual TreeThe only thing that I can think of to get around this is to bind both of the CheckBoxes to a common ancestor, e.g. the parent
DataGrid
and use an attached property or theTag
property. Exampleand
我认为常规数据绑定到
HeaderCheckBox
是不可能的,因为CheckBox
作为Template
的一部分存在,并且位于不同的分支中VisualTree
的值比DataGridItems
的值通常相反:当标题
CheckBox
被选中时,检查所有行CheckBoxes< /代码>。我这样做的主要原因是因为复选框通常在那里,因此用户可以选中/取消选中它们,如果它们绑定到标题复选框选中状态,则用户无法更改它们。
为了实现这一点,我通常挂接到 Header CheckBox 的
Click
或Checked
事件。如果行
CheckBox.IsChecked
状态绑定到 ViewModel 中的某些内容,我会将事件挂钩到 ViewModel 中的Command
,并设置 < code>CheckBox.IsChecked 绑定到true
/false
,具体取决于标头 CheckBox 状态(通常作为CommandParameter
传入) )如果
CheckBox.IsChecked
状态不绑定到任何东西,您可以使用常规代码隐藏来循环DataGrid.Items
,使用ItemContainerGenerator
来获取每个项目的 ItemContainer,找到CheckBox
,然后设置其选中状态。I don't think regular DataBinding to the
HeaderCheckBox
is possible because theCheckBox
exists as part of aTemplate
, and it is in a different branch of theVisualTree
than theDataGridItems
Usually I make it the reverse: When the header
CheckBox
gets checked, check all the rowCheckBoxes
. My main reason for this is because the CheckBoxes are usually there so users can check/uncheck them, and if they're bound to the header CheckBox checked state, then the user can't alter them.For implementing that, I usually hook into the
Click
orChecked
event of the Header CheckBox.If the row
CheckBox.IsChecked
state is bound to something in a ViewModel, I'll hook the event to aCommand
in my ViewModel, and set the data item that theCheckBox.IsChecked
is bound to totrue
/false
depending on the header CheckBox state (usually passed in as aCommandParameter
)If the
CheckBox.IsChecked
state is not bound to anything, you can use regular code-behind to loop through yourDataGrid.Items
, use theItemContainerGenerator
to get the ItemContainer for each item, find theCheckBox
, and then set it's check state.