Abdullah Malikyar
Abdullah Malikyar

Reputation: 231

C# - FrameworkElement.FindName returns null

I spent the past one hour trying to figure this out. I have a CheckBox inside DataGrid as follows:

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

As you can see I am trying to check and uncheck the CheckBoxes inside DataGrid rows when the CheckBox in the header is checked or unchecked. This is the code where I am trying to retrieve the CheckBox and mark it as checked:

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

I have already tried RegisterName() method and I've tried VisualTreeHelper but nothing works.

This line always returns null:

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

Here is a WPF visualizer screenshot for my FrameworkElement where I can clearly see the checkbox I am trying to find:

WPF visualizer screenshot of FrameworkElement

Please tell me what am I doing wrong? Thank you.

Upvotes: 0

Views: 3295

Answers (3)

Grx70
Grx70

Reputation: 10349

The thing is that a DataTemplate is a name scope boundary, that is the templated element (a ContentPresenter in this case) or any of it's ancestors are not aware of named elements defined inside the template. In order to find a named element inside the template you need to use the DataTemplate.FindName method instead (inherited from FrameworkTemplate). Notice that it takes two parameters instead of one, the second one being the templated element. This should do the trick for you:

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

Upvotes: 3

mm8
mm8

Reputation: 169360

Try this:

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

Upvotes: 0

Mishka
Mishka

Reputation: 516

The CheckBox does not exist in the scope that the Row knows. It is not a Direct child of its Template.

You need to use the static class VisualTreeHelper to drill down from the row to find an instance of type CheckBox, and compare against its x:Name.

Upvotes: 0

Related Questions