如何获取 DataGridTemplateColumn 的底层(文本框)控件
How to get the underlying (TextBox) Control of a DataGridTemplateColumn
我使用此代码将 TextBox 添加到 DataGrid 单元格:(不,我不能在此处使用 XAML)
Binding binding = new Binding("Fld_Company");
binding.Mode = BindingMode.OneWay;
FrameworkElementFactory frameworkElementFactory = new FrameworkElementFactory(typeof(TextBox));
DataTemplate dataTemplate = new DataTemplate();
dataTemplate.VisualTree = frameworkElementFactory;
frameworkElementFactory.SetBinding(TextBox.TextProperty, binding);
DataGridTemplateColumn dataGridTemplateColumn = new DataGridTemplateColumn();
dataGridTemplateColumn.IsReadOnly = true;
dataGridTemplateColumn.Header = "Company";
dataGridTemplateColumn.CellTemplate = dataTemplate;
this.dataGrid.Columns.Add(dataGridTemplateColumn);
我有办法在没有 XAML 的情况下获取底层 TextBox 控件吗?
我尝试了什么:
- VisualTreeHelper,但 GetChildrenCount() 始终为 0
- FindName,但我还没有找到合适的
FrameworkElement
在研究了 DataGrid 一段时间后,我发现我的问题没有任何意义。我上面的代码只准备了 DataGrid 但没有填充任何数据。直到没有生成任何行,因此找不到 underlying TextBox controls
。
当 DataGrid 最终填满数据时,获取底层控件的最佳方法似乎是捕获 LoadinRow
事件。但是当这个事件触发时,行的加载还没有完成。需要临时分配第二个事件,该事件在最终加载行时触发。
{
DataGrid.LoadingRow += DataGrid_LoadingRow;
}
private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
// The visual tree is not built until the row is "loaded". This event fires when this happend:
e.Row.Loaded += DataGrid_Row_Loaded;
}
private void DataGrid_Row_Loaded(object sender, RoutedEventArgs e)
{
DataGridRow dataGridRow = (DataGridRow)sender;
// important: Remove the event again
dataGridRow.Loaded -= DataGrid_Row_Loaded;
NestedGridFieldProperty ngrProp = (NestedGridFieldProperty)dataGridRow.Item;
// Get the "presenter", which contains the cells
DataGridCellsPresenter presenter = coNeboTools.ConeboMisc.GetVisualChild<DataGridCellsPresenter>(dataGridRow);
// Get the cells in the presenter
var cells = GetVisualChildren<DataGridCell>(presenter);
// Get the underlying TextBox in column 0
TextBox underlyingTextBox = (TextBox)cells.ElementAt(0).Content;
// the Item property of the row contains the row data
var myData = dataGridRow.Item;
// do what ever is needed with the TextBlock
underlyingTextBox.Foreground = Brushes.Red;
}
// Static helper method to handle the visual tree
public static IEnumerable<T> GetVisualChildren<T>(DependencyObject dependencyObject)
where T : DependencyObject
{
if (dependencyObject != null)
{
int childrenCount = VisualTreeHelper.GetChildrenCount(dependencyObject);
for (int i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in GetVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
// Static helper method to handle the visual tree
public static childItem GetVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
foreach (childItem child in GetVisualChildren<childItem>(obj))
{
return child;
}
return null;
}
我使用此代码将 TextBox 添加到 DataGrid 单元格:(不,我不能在此处使用 XAML)
Binding binding = new Binding("Fld_Company");
binding.Mode = BindingMode.OneWay;
FrameworkElementFactory frameworkElementFactory = new FrameworkElementFactory(typeof(TextBox));
DataTemplate dataTemplate = new DataTemplate();
dataTemplate.VisualTree = frameworkElementFactory;
frameworkElementFactory.SetBinding(TextBox.TextProperty, binding);
DataGridTemplateColumn dataGridTemplateColumn = new DataGridTemplateColumn();
dataGridTemplateColumn.IsReadOnly = true;
dataGridTemplateColumn.Header = "Company";
dataGridTemplateColumn.CellTemplate = dataTemplate;
this.dataGrid.Columns.Add(dataGridTemplateColumn);
我有办法在没有 XAML 的情况下获取底层 TextBox 控件吗?
我尝试了什么:
- VisualTreeHelper,但 GetChildrenCount() 始终为 0
- FindName,但我还没有找到合适的
FrameworkElement
在研究了 DataGrid 一段时间后,我发现我的问题没有任何意义。我上面的代码只准备了 DataGrid 但没有填充任何数据。直到没有生成任何行,因此找不到 underlying TextBox controls
。
当 DataGrid 最终填满数据时,获取底层控件的最佳方法似乎是捕获 LoadinRow
事件。但是当这个事件触发时,行的加载还没有完成。需要临时分配第二个事件,该事件在最终加载行时触发。
{
DataGrid.LoadingRow += DataGrid_LoadingRow;
}
private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
// The visual tree is not built until the row is "loaded". This event fires when this happend:
e.Row.Loaded += DataGrid_Row_Loaded;
}
private void DataGrid_Row_Loaded(object sender, RoutedEventArgs e)
{
DataGridRow dataGridRow = (DataGridRow)sender;
// important: Remove the event again
dataGridRow.Loaded -= DataGrid_Row_Loaded;
NestedGridFieldProperty ngrProp = (NestedGridFieldProperty)dataGridRow.Item;
// Get the "presenter", which contains the cells
DataGridCellsPresenter presenter = coNeboTools.ConeboMisc.GetVisualChild<DataGridCellsPresenter>(dataGridRow);
// Get the cells in the presenter
var cells = GetVisualChildren<DataGridCell>(presenter);
// Get the underlying TextBox in column 0
TextBox underlyingTextBox = (TextBox)cells.ElementAt(0).Content;
// the Item property of the row contains the row data
var myData = dataGridRow.Item;
// do what ever is needed with the TextBlock
underlyingTextBox.Foreground = Brushes.Red;
}
// Static helper method to handle the visual tree
public static IEnumerable<T> GetVisualChildren<T>(DependencyObject dependencyObject)
where T : DependencyObject
{
if (dependencyObject != null)
{
int childrenCount = VisualTreeHelper.GetChildrenCount(dependencyObject);
for (int i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in GetVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
// Static helper method to handle the visual tree
public static childItem GetVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
foreach (childItem child in GetVisualChildren<childItem>(obj))
{
return child;
}
return null;
}