2014-03-24 18 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

相关问题