Home > Software engineering >  How do you get all the Textbox from a DataGrid?
How do you get all the Textbox from a DataGrid?

Time:07-30

I simply want to achieve the same thing like this;

MyTextBox.GetBindingExpression(TextBox.TextProperty).UpdateSource(); //this will forcely update source of this TextBox.

I have a DataGrid with DataTemplate.

<DataGrid x:Name="MyDataGrid">
     <DataGrid.Columns>
        .....
        <DataGridTemplateColumn MinWidth="50" DisplayIndex="4">
            <DataGridTemplateColumn.HeaderTemplate>
                <DataTemplate>
                 ....
                </DataTemplate>
            </DataGridTemplateColumn.HeaderTemplate>
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBox x:Name="TheTextBox">
                        ....
                    </TextBox>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </Datagrid.Columns>
 </DataGrid>

I got NullReferenceException on this;

for (int x = 0; x < MyDataGrid.Items.Count; x  )
{
    TextBox? ele = ((ContentPresenter)(MyDataGrid.Columns[2].GetCellContent(x))).Content as TextBox;
    ele.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}

Basically, what I want is to forcibly update the source of the TextBoxes in my DataGrid.

CodePudding user response:

It looks this is not simple as I thought. It needs two methods in order to get the TextBox from the DataGrid.

First, using the GetVisualChild;

public static T? GetVisualChild<T>(Visual parent) where T : Visual{
   for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i  ){
      Visual visual = (Visual)VisualTreeHelper.GetChild(parent, i);
      if (visual is not T child) child = GetVisualChild<T>(visual);
      if (child != null) return child;
   }
   return default;
}

Second, using FindVisualChild;

public T? FindVisualChild<T>(DependencyObject obj, string name) where T : DependencyObject{
   for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i  ){
      DependencyObject child = VisualTreeHelper.GetChild(obj, i);
      if (child != null && child is T t && child is FrameworkElement frameworkElement && frameworkElement.Name == name) return t;
      T childOfChild = FindVisualChild<T>(child, name);
      if (childOfChild != null) return childOfChild;
    }
    return null;
}

Combining these two in order to get the TextBox;

for (int i = 0; i < MyDataGrid.Items.Count; i  ){
    DataGridRow dataGridRow = (DataGridRow)MyDataGrid.ItemContainerGenerator.ContainerFromIndex(i);
    DataGridCellsPresenter dataGridCellsPresenter = GetVisualChild<DataGridCellsPresenter>(dataGridRow);
    for (int j = 0; j < MyDataGrid.Columns.Count; j  ){
        TextBox textBox = FindVisualChild<TextBox>((DataGridCell)dataGridCellsPresenter.ItemContainerGenerator.ContainerFromIndex(j), "TheTextBox"); // I also need to specify the name of the TextBox from my DataTemplate.
        if (textBox != null) textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource(); //updatesource of the TextBox
    }
}

Somehow it solves my problem.

  • Related