从DataGrid中查找聚焦单元格

时间:2014-03-24 10:27:40

标签: wpf datagrid focus

我需要实现一个"复制值到剪贴板"应该可以通过所有公共通道使用的WPF DataGrid的函数:右键单击上下文菜单项;菜单键上下文菜单项; Ctrl + C热键。数据网格内容来自数据绑定,但由于复制命令是仅查看的内容,因此它完全在视图层中实现,而不是视图模型。所以我不会使用ICommand,但只能使用代码中的事件处理程序。

DataGrid的SelectionUnit设置为FullRow,但箭头导航键仍然有效,单个单元格可以看到焦点矩形。因此,当选择完整行时,可以聚焦单个单元。对于此命令,我需要确定聚焦单元格。

菜单项已经很复杂了。它的Click事件为我提供了MenuItem实例,我可以从中导航到ContextMenu并进一步导航到DataGrid。这就是全部,没有点击的单元格。我已经知道如何获取DataGrid,一次只能看到其中一个。

我现在需要找出哪个细胞聚焦了。但我甚至无法获得所选单元格或行甚至所有行的列表。我能找到的所有属性只是指向信息的一些片段,而DataGrid.Rows只是不存在。我可以扫描整个可视树以获得一些专注的DataGridCell,但这可能效率不高。

有什么想法吗?

稍后我还需要第二个功能"将选定的行复制到剪贴板"它以可以粘贴到Excel(制表符分隔的行)的格式复制所有选定行中所有单元格的值。

1 个答案:

答案 0 :(得分:2)

辅助功能:

    /// <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;
    }

加载DataGrid后,您可以调用它:

    /// <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属性。