C#-FrameworkElement.FindName返回null

C#-FrameworkElement.FindName返回null,c#,wpf,datagrid,datatemplate,C#,Wpf,Datagrid,Datatemplate,我花了一个小时试图弄明白这一点。我在DataGrid中有一个复选框,如下所示: <DataGridTemplateColumn> <DataGridTemplateColumn.Header> <CheckBox Name="chkall" Content="Select All" Checked="chkall_Checked" Unchecked="chkall_Unchecked"/> </DataGridTempl

我花了一个小时试图弄明白这一点。我在
DataGrid
中有一个
复选框,如下所示:

<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>
我已经尝试了
RegisterName()
方法,也尝试了
visualtreeheloper
,但没有任何效果

此行始终返回
null

var checkbox = FW_element.FindName("chksingle") as CheckBox;
这是我的
FrameworkElement
的WPF visualizer屏幕截图,在这里我可以清楚地看到我试图找到的复选框:


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

该复选框不在该行知道的范围内。它不是其模板的直接子级

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

尝试以下操作:

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

问题是,
DataTemplate
是一个名称范围边界,即模板化元素(在本例中是
ContentPresenter
),或者它的任何祖先都不知道模板中定义的命名元素。为了在模板中查找命名元素,您需要改用该方法(继承自
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;
    }
}
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;
    }
}