【问题标题】:DataTrigger in CellTemplate binding to HeaderTemplate; can it work?CellTemplate 中的 DataTrigger 绑定到 HeaderTemplate;它可以工作吗?
【发布时间】:2011-11-06 22:29:34
【问题描述】:

这里的目标是在标题复选框更改时检查所有网格复选框:

<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>

看起来像:

由于某种原因,触发器没有触发。

有什么想法吗?

【问题讨论】:

    标签: wpf datagrid datatrigger


    【解决方案1】:

    如您所见,DataTemplate 内的ElementName 绑定无法访问模板之外的元素。这是因为它可以被多次实例化并且有自己的名称范围,因此您在DataTemplate 中创建的任何ElementName 绑定都会在模板内查找具有该名称的另一个元素。

    用 Snoop 查看它,我们还可以看到 RelativeSource 绑定不能直接使用,因为它们位于 Visual Tree 的不同部分

    我能想到的唯一解决方法是将两个 CheckBox 绑定到一个共同的祖先,例如父 DataGrid 并使用附加属性或 Tag 属性。示例

    <Style TargetType="CheckBox" x:Key="InnerBox">
        <Setter Property="HorizontalAlignment" Value="Center" />
        <Setter Property="IsChecked" Value="False" />
        <Style.Triggers>
            <DataTrigger Value="True"
                         Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
                                           Path=Tag}">
                <Setter Property="IsChecked" Value="True" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
    

    <DataTemplate>
        <!-- header check -->
        <CheckBox Name="HeaderCheckbox"
                  IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
                                      Path=Tag,
                                      Mode=OneWayToSource}"/>
    </DataTemplate>
    

    【讨论】:

    • 聪明,如果使用Tag,可以添加一个Attached Property。
    【解决方案2】:

    我认为不可能对HeaderCheckBox 进行常规DataBinding,因为CheckBox 作为Template 的一部分存在,并且它与VisualTree 位于VisualTree 的不同分支中

    通常我会反过来:当标题 CheckBox 被检查时,检查所有行 CheckBoxes。我这样做的主要原因是因为 CheckBoxes 通常在那里,因此用户可以选中/取消选中它们,并且如果它们绑定到标题 CheckBox 选中状态,则用户无法更改它们。

    为了实现这一点,我通常会挂钩到 Header CheckBox 的 ClickChecked 事件。

    如果行 CheckBox.IsChecked 状态绑定到 ViewModel 中的某些内容,我会将事件挂钩到我的 ViewModel 中的 Command,并将 CheckBox.IsChecked 绑定到的数据项设置为 true /false 取决于标头 CheckBox 状态(通常作为 CommandParameter 传入)

    如果CheckBox.IsChecked 状态没有绑定到任何东西,您可以使用常规代码隐藏循环您的DataGrid.Items,使用ItemContainerGenerator 获取每个项目的ItemContainer,找到CheckBox,然后然后设置它的检查状态。

    【讨论】:

    • 对不起,你的回答对我来说没有意义。问题是关于绑定到 HeaderTemplate 的 CellTemplate 中的 DataTriggers。我没有在问题中使用命令或 ViewModel。我想我真的只是想知道这是否可以做到。我意识到使用触发器以外的东西可以做同样的事情。很抱歉,我的问题没有更清楚。
    • @Jerry 我确信这是可能的,但它需要一些非常不寻常的解决方法,例如在 Visual Tree 中搜索 Header CheckBox 的转换器。我建议您在走这条路并检查替代方案之前重新评估您要完成的工作。
    • 我认为不可能对 HeaderCheckBox 进行常规 DataBinding,因为 CheckBox 存在于模板中,并且它与 DataGridItems 位于 VisualTree 的不同分支中
    猜你喜欢
    • 2010-09-08
    • 2016-10-18
    • 2014-08-26
    • 2015-08-03
    • 2017-01-23
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2012-07-01
    相关资源
    最近更新 更多