C# - FrameworkElement.FindName returns 空

C# - FrameworkElement.FindName returns null

我花了一个小时试图解决这个问题。我在 DataGrid 里面有一个 CheckBox 如下:

<DataGridTemplateColumn>
    <DataGridTemplateColumn.Header>
        <CheckBox Name="chkall" Content="Select All" Checked="chkall_Checked" Unchecked="chkall_Unchecked"/>
    </DataGridTemplateColumn.Header>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <CheckBox Tag="{Binding Path=id}" x:Name="chksingle"  Checked="chksingle_Checked" Unchecked="chksingle_Unchecked"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

如您所见,当 header 中的 CheckBox 被选中或未选中时,我正在尝试选中和取消选中 DataGrid 行中的 CheckBoxes。这是我试图检索 CheckBox 并将其标记为选中的代码:

private void chkall_Checked(object sender, RoutedEventArgs e)
{
    foreach (var r in userDG.Items)
    {
        DataGridRow row =(DataGridRow)userDG.ItemContainerGenerator.ContainerFromItem(r);
        FrameworkElement FW_element = userDG.Columns[0].GetCellContent(row);
        FW_element.ApplyTemplate();
        var checkbox = FW_element.FindName("chksingle") as CheckBox;
        checkbox.IsChecked = false;
    }
}

我已经尝试了 RegisterName() 方法并且我已经尝试 VisualTreeHelper 但没有任何效果。

这一行总是returns null:

var checkbox = FW_element.FindName("chksingle") as CheckBox;

这是我的 FrameworkElementWPF 可视化工具 屏幕截图,我可以在其中清楚地看到我要查找的复选框:

请告诉我我做错了什么?谢谢。

CheckBox 在 Row 知道的范围内不存在。它不是其模板的直接子项。

您需要使用静态 class VisualTreeHelper 从该行向下钻取以查找 CheckBox 类型的实例,并与其 x:Name.

进行比较

试试这个:

FrameworkElement FW_element = userDG.Columns[0].GetCellContent(row);
CheckBox checkbox = VisualTreeHelper.GetChild(FW_element, 0) as CheckBox;

问题是 DataTemplate 是名称范围边界,即模板化元素(在本例中为 ContentPresenter)或其任何祖先都不知道内部定义的命名元素模板。为了在模板中找到命名元素,您需要使用 DataTemplate.FindName 方法(继承自 FrameworkTemplate)。请注意,它采用两个参数而不是一个参数,第二个参数是模板化元素。这应该可以为您解决问题:

private void chkall_Checked(object sender, RoutedEventArgs e)
{
    foreach (var r in userDG.Items)
    {
        DataGridRow row = (DataGridRow)userDG.ItemContainerGenerator.ContainerFromItem(r);
        FrameworkElement FW_element = userDG.Columns[0].GetCellContent(row);
        //We use the CellTemplate defined on the column to find the CheckBox
        var checkbox = ((DataGridTemplateColumn)userDG.Columns[0]).CellTemplate.FindName("chksingle", FW_element) as CheckBox;
        checkbox.IsChecked = true;
    }
}