2014-07-13 43 views
0

我有一個包含一些列的DataGrid。其中之一是模板列。這TemplateColumn中的聲明如下所示:獲取DataGrid中DataGridTemplateColumn中的文本框的文本

<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中的細胞,我想裏面的TextBlock文本。因此,我使用了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的內容爲空。

+2

您已經綁定到FirstName,那麼爲什麼不訪問DataContext並只使用FirstName屬性? –

+0

http://stackoverflow.com/questions/16997951/how-to-access-datagrid-template-column-textbox-text-wpf-c-sharp – Sajeetharan

+0

@ d.moncada對不起,由於電力故障遲到的答覆。只要我在一個單元格中輸入一些數據,然後按回車,我想要它的值。那時FirstName屬性是null,所以我不能使用它。 – Vishal

回答

0

我已經解決了我的問題。我從e.OriginalSource獲得了當前正在編輯的文本框。

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屬性爲空。

​​
1

一些評論表明,訪問ViewModel可能是一種選擇這裏,而這將是在某些情況下,更簡單的方法,它不處理非數據綁定的領域,是最有可能會不那麼普通確實。

我們想要做的是找到第一個TextBlock孩子走下VisualTree點擊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方法(下實現)。該方法將所有的孩子放下,直到找到深度優先搜索中的第一個文本框發生爲止。額外的好處是,這也適用於標準的自動生成的列!

private static T FindVisualChild<T>(DependencyObject item) 
    where T : DependencyObject 
{ 
    var childCount = VisualTreeHelper.GetChildrenCount(item); 
    var result = item as T; 
    //the for-loop contains a null check; we stop when we find the result. 
    //so the stop condition for this method is embedded in the initialization 
    //of the result variable. 
    for (int i = 0; i < childCount && result == null; i++) 
    { 
     result = FindVisualChild<T>(VisualTreeHelper.GetChild(item, i)); 
    } 
    return result; 
} 

有關如何尋找孩子,請看看this page,解釋視覺樹和WPF邏輯樹之間的區別更多的信息和了解。