我有一些包含一些列的DataGrid。其中一个是模板列。 TemplateColumn的声明如下所示:
<DataGridTemplateColumn Header="First Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding FirstName}" Loaded="TextBox_Loaded_1"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
要求:
以通用方式获取驻留在CellTemplate内的TextBlock中的文本。
我尝试了什么:
当我在TemplateColumn的单元格上按Enter键时,我想要TextBlock中的Text。所以,我使用了DataGrid的PreviewKeyDown事件,如下所示:
private void DataGrid_PreviewKeyDown(.............)
{
If(e.Key == Key.Enter)
{
DependencyObject dep = (DependencyObject)e.OriginalSource;
if(dep != null && dep is DataGridCell)
{
var CellTemplate = ((DataGridCell)dep).Content; //gives me ContentPresenter instead of Textblock
if (CellTemplate is TextBlock)
{
if (((TextBlock)CellTemplate).Text.Trim() == "")
{
//Do whatever I want
}
}
}
}
}
上述代码返回ContentPresenter而不是TextBlock。为什么会这样?
此外,ContentPresenter的内容为空。
答案 0 :(得分:1)
在绑定中,您可以使用UpdateSourceTrigger=PropertyChanged
,这样在DataGrid_PreviewKeyDown
中您就不会将FirstName属性视为null。
<DataGridTemplateColumn Header="First Name">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding FirstName}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<TextBox Text="{Binding FirstName, UpdateSourceTrigger=PropertyChanged}" Loaded="TextBox_Loaded_1"/>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
在DataGrid_PreviewKeyDown
事件中,您可以按如下方式获取行数据项,这次您不会将Name属性设置为null。
private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
var cell = e.OriginalSource as DataGridCell;
if (cell != null)
{
var dataitem = cell.DataContext; //Here you can you AS keyword to convert the DataContext to your item type.
//dataitem.FirstName
}
}
}
答案 1 :(得分:1)
有些评论表明访问ViewModel
可能是一种选择,而在某些情况下,这将是更简单的方法,它不会处理非数据绑定字段,并且很可能会更少通用的。
我们要做的是找到第一个TextBlock
孩子沿着点击的VisualTree
的{{1}}行走。请考虑以下示例:
DataGridCell
在背后的代码中:
<DataGrid Name="Test" PreviewKeyDown="DataGrid_PreviewKeyDown">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="Bla Bla 123" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
神奇之处在于private void DataGrid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
var pressedCell = e.OriginalSource as DataGridCell;
if (pressedCell != null)
{
var textBlock = FindVisualChild<TextBlock>(pressedCell);
if (textBlock != null)
{
MessageBox.Show("Text: " + textBlock.Text);
//or more useful stuff
}
}
}
}
方法(下面的实现)。该方法向下遍历所有子项,直到它在深度优先搜索中发现第一个文本框出现。额外的好处是,这也适用于标准的自动生成列!
FindVisualChild
有关如何搜索孩子的更多信息和理解,请查看this page,解释可视化树与WPF中逻辑树之间的区别。
答案 2 :(得分:0)
我已经解决了我的问题。我从e.OriginalSource获得了当前正在编辑的文本框。