获取驻留在DataGrid中的DataGridTemplateColumn内的TextBox文本

时间:2014-07-13 15:47:29

标签: c# wpf datagrid

我有一些包含一些列的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的内容为空。

3 个答案:

答案 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获得了当前正在编辑的文本框。