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.