2011-10-25 144 views
0

我們有這樣一個場景,我們有一個包含DataGrid的頁面,現在我們想要從這個DataGrid獲取所有數據,但是沒有訪問它的基礎項源,也就是說,我們希望直接從數據源訪問數據DataGrid。這似乎很棘手,但並非不可能。我發現了很多文章,像這樣:DataGridHelper,和這個:Get WPF DataGrid row and cell,和許多其他的。它們基本上是一樣的:在另一個GetVisualChild函數的幫助下,在DataGrid上定義擴展方法來查找目標DataGridCell對象。但是,當我使用它時,我無法找到目標單元格。具體來說,DataGrid中的每一行對應於DataContext集合中的一個項目,假設它是「Employee」類型的集合,並且DataGrid的每一列都對應Employee類的一個屬性,例如Name,Gender ,年齡。現在我的問題是,上面提到的GetCell()函數總是找到一個DataGridCell,其中一個Employee對象作爲其內容(DataGridCell中Content的屬性),並且無論我給出的列索引如何,都無法進一步進入每個屬性它。 例如,在GetCell函數中,有一行: Dim cell As DataGridCell = DirectCast(presenter.ItemContainerGenerator.ContainerFromIndex(column), DataGridCell), 其中演示者是一個DataGridCellsPresenter我得到了表示我選擇的行,並且一旦我給列索引,自然我期待它返回指定位置I的選定屬性的控制。但它不能按預期工作。任何幫助,將不勝感激!訪問WPF中DataGrid的單元格值?

回答

0

當你使用presenter.ItemContainerGenerator.ContainerFromIndex時,你陷入了一個限制,它只能用於非虛擬化的項目,即在滾動視圖中顯示的行(加上滾動視圖限制上下的一些偏移行數)數據網格。

爲了您訪問所有單元格的值,您必須爲每行執行列級綁定。

  1. 訪問DataGrid.Items集合。這是項目的視圖,因此任何通過過濾標準或自定義分頁等隱藏的項目都將被排除。如果你不想那麼請撥打DataGrid.ItemsSource.Cast<object>().ToList()

  2. 現在訪問數據網格的所有列,即DataGrid.Columns。假設它們是任何類型,但是DataGridTemplateColumn,下面的步驟3將提取單元級別的值。對於模板列,您必須指定一些代表單元格整個模板的屬性值。我發現DataGridTemplateColumn.SortMemberPath是一個很好的候選人。

  3. 提取DataGridTextColumn.Binding,DataGridCheckBoxColumn.Binding,DataGridComboBoxColumn.SelectedValueBindingDataGridComboBoxColumn.SelectedItemBinding。然後對於步驟1中的每個項目,執行綁定以提取值。

代碼

private void Button_Click_1(object sender, RoutedEventArgs e) 
    { 
     string gridContent = string.Empty; 

     foreach(var item in MyDataGrid.Items) 
     { 
      foreach (var column in MyDataGrid.Columns) 
      { 
       var textCol = column as DataGridTextColumn; 
       var checkCol = column as DataGridCheckBoxColumn; 
       var comboCol = column as DataGridComboBoxColumn; 
       var templateCol = column as DataGridTemplateColumn; 

       if (textCol != null) 
       { 
        var propertyName = ((Binding)textCol.Binding).Path.Path; 
        var value 
          = item.GetType().GetProperty(
            propertyName).GetValue(
            item, 
            new object[] {}); 

        if (((Binding)textCol.Binding).Converter != null) 
        { 
         value 
          = ((Binding)checkCol.Binding).Converter.Convert(
           value, 
           typeof(object), 
           ((Binding)checkCol.Binding).ConverterParameter, 
           ((Binding)checkCol.Binding).ConverterCulture); 
        } 
        gridContent = gridContent + "\t" + value.ToString(); 
       } 
       if (checkCol != null) 
       { 
        var propertyName = ((Binding)checkCol.Binding).Path.Path; 
        object value 
         = item.GetType().GetProperty(
           propertyName).GetValue(
           item, 
           new object[] { }); 

        if (((Binding)checkCol.Binding).Converter != null) 
        { 
         value 
          = ((Binding)checkCol.Binding).Converter.Convert(
           value, 
           typeof(object), 
           ((Binding)checkCol.Binding).ConverterParameter, 
           ((Binding)checkCol.Binding).ConverterCulture); 
        } 
        gridContent = gridContent + "\t" + value.ToString(); 
       } 
       if (comboCol != null) 
       { 
        var propertyName = string.Empty; 
        if (comboCol.SelectedValueBinding != null) 
        { 
         propertyName 
          = ((Binding)comboCol.SelectedValueBinding).Path.Path; 
        } 
        else if (!string.IsNullOrEmpty(comboCol.SelectedValuePath)) 
        { 
         propertyName = comboCol.SelectedValuePath; 
        } 
        else if (!string.IsNullOrEmpty(comboCol.DisplayMemberPath)) 
        { 
         propertyName = comboCol.DisplayMemberPath; 
        } 

        var value = item.GetType().GetProperty(
         propertyName).GetValue(
          item, 
          new object[] { }); 

        if (comboCol.SelectedValueBinding != null 
         && ((Binding)comboCol.SelectedValueBinding).Converter != null) 
        { 
         var bnd = (Binding)comboCol.SelectedValueBinding; 
         value 
          = bnd.Converter.Convert(
           value, 
           typeof(object), 
           bnd.ConverterParameter, 
           bnd.ConverterCulture); 
        } 
        gridContent = gridContent + "\t" + value.ToString(); 
       } 
       if (templateCol != null) 
       { 
        var propertyName = templateCol.SortMemberPath; 
        var value 
         = item.GetType().GetProperty(
          propertyName).GetValue(
           item, 
           new object[] { }); 

        gridContent = gridContent + "\t" + value.ToString(); 
       } 
      } 

      gridContent = gridContent + "\n"; 
     } 

     MessageBox.Show(gridContent); 
    } 
} 
+0

感謝您的幫助!這幾乎清除了我的問題。但是我的情況是,我現在可以獲得DataGrid背後的屬性值,但不幸的是,這不是我想要的。仍然以我的Employee爲例,現在我可以獲得Name,Gender,Age的屬性值,這可能是一些類實例。例如,類名稱和性別。但我想要的是在DataGrid的TextBlock中顯示的文本。例如,我可能會選擇在「名稱」單元格中顯示名字,因此僅獲取名稱實例是不夠的。我想訪問單元格的原因(待續) – tete

+0

TextBlock值(而不是屬性本身)是,我在每個DataGrid單元格中使用了很多自定義的TextBlock,它根據用戶的選擇進行格式設置。在運行時沒有簡單的方法來獲得這種格式化信息。或者我可以說我們希望避免它,因爲只要格式化的值已經存在於某處,它就有點多餘。例如,用戶可以設置顯示員工姓名的首字母,我們自定義的TextBlock已經顯示了這些姓名的首字母。所以我很自然地想知道這些縮寫,而不知道用戶選擇了什麼樣的格式。 – tete

+0

我現在猜測我需要做的是通過所有存儲我們定製的TextBlock信息的Visuals,並且我可以直接獲取文本值,並且可能還需要我也需要的顏色信息。有沒有辦法做到這一點?再次感謝,我知道我可能已經問太多了:) – tete

0

我意識到這是老話題,但我尋找一個簡單的解決方案,並終於找到了。以爲其他人可能喜歡簡單。以下示例通過指定的列搜索數據網格以獲得所需的值,如果找到則選擇該行。

private void dgSetRow(DataGrid dg, string sColHeader, int iFindValue) 
    { 

     foreach (DataRowView drv in dg.Items) 
     { 
      // compare value in datarow of view 
      if (iFindValue == (int)drv.Row[sColHeader]) 
      { 
       // select item 
       dg.SelectedItem = drv; 
       dg.ScrollIntoView(drv); 
      } 
     } 
    }