2014-03-24 47 views
1

我需要爲應通過所有公共通道提供的WPF DataGrid實現「複製值到剪貼板」功能:右鍵單擊上下文菜單項;菜單鍵上下文菜單項; Ctrl + C熱鍵。數據網格內容來自數據綁定,但由於複製命令是一個只能查看的東西,因此它完全在視圖層中實現,而不是視圖模型。所以我不使用ICommand來處理這個事件,而只使用事件處理器來處理代碼。從DataGrid中查找聚焦的單元格

DataGrid的SelectionUnit設置爲FullRow,但箭頭導航鍵仍然有效,單個單元格可以看到焦點矩形。因此,在選擇完整行時可以聚焦單個單元。對於這個命令,我需要確定聚焦的單元格。

菜單項已經非常複雜。它的Click事件給了我MenuItem實例,從中我可以導航到ContextMenu並進一步到DataGrid。就是這樣,沒有點擊的單元格。我已經知道如何獲得DataGrid,一次只能看到其中一個。

我現在需要找出哪個單元格重點。但我甚至無法獲得所選單元格或行甚至所有行的列表。我可以找到的所有屬性都指向信息的一些片段,而DataGrid.Rows則不存在。我可以掃描整個可視化樹中的一些重點DataGridCell,但這可能不是很有效。

任何想法?

後來我還需要第二個功能「將選定的行復制到剪貼板」,以可以粘貼到Excel(製表符分隔的行)的格式複製所有選定行中所有單元格的值。

回答

2

一個輔助函數:DataGrid中加載

/// <summary> 
    /// Look for child element 
    /// </summary> 
    /// <typeparam name="childItem">Child Item</typeparam> 
    /// <param name="obj">Dependency Object</param> 
    /// <returns>The child or null</returns> 
    private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject 
    { 
     if (obj == null) 
     { 
      return null; 
     } 

     int childCount = VisualTreeHelper.GetChildrenCount(obj); 

     for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) 
     { 
      DependencyObject child = VisualTreeHelper.GetChild(obj, i); 

      if (child != null && child is childItem) 
      { 
       return (childItem)child; 
      } 
      else 
      { 
       childItem childOfChild = this.FindVisualChild<childItem>(child); 

       if (childOfChild != null) 
       { 
        return childOfChild; 
       } 
      } 
     } 

     return null; 
    } 

後,你可以調用這個:

/// <summary> 
    /// Get the cell of the datagrid. 
    /// </summary> 
    /// <param name="dataGrid">The data grid in question</param> 
    /// <param name="cellInfo">The cell information for a row of that datagrid</param> 
    /// <param name="cellIndex">The row index of the cell to find. </param> 
    /// <returns>The cell or null</returns> 
    private DataGridCell TryToFindGridCell(DataGrid dataGrid, DataGridCellInfo cellInfo, int cellIndex = -1) 
    { 
     DataGridRow row; 
     DataGridCell result = null; 

     if (cellIndex < 0) 
     { 
      row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromItem(cellInfo.Item); 
     } 
     else 
     { 
      row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(cellIndex); 
     } 

     if (row != null) 
     { 
      int columnIndex = dataGrid.Columns.IndexOf(cellInfo.Column); 

      if (columnIndex > -1) 
      { 
       DataGridCellsPresenter presenter = this.FindVisualChild<DataGridCellsPresenter>(row); 

       if (presenter != null) 
       { 
        result = presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex) as DataGridCell; 
       } 
       else 
       { 
        result = null; 
       } 
      } 
     } 

     return result; 
    } 

然後你得到你的細胞後,只是檢查IsFocused屬性。

+1

謝謝。這解決了尋找聚焦細胞的內容。不幸的是,我發現點擊的單元格只在以前沒有選擇該行時纔會關注。當右鍵單擊同一行中的另一個單元格時,焦點不會移動,並且出現錯誤的單元格。但這是我原來的問題。 – ygoe

+0

有趣。我想知道你是否不能取消選擇行..?稍後可能會深入研究。 – ouflak

+0

我在此期間更改了該代碼。如果按下Apps鍵,我只使用聚焦的單元格作爲基礎,然後打開單元格右下方的上下文菜單。當右鍵單擊時,我使用e.OriginalSource並在可視化樹中查找DataGridCell父級。在這種情況下,我也打開單元格右下方的上下文菜單。只有在找不到細胞的情況下,才使用鼠標位置。 – ygoe

相關問題