我需要实现一个WPF DataGrid的"复制值到剪贴板"功能,应该可以通过所有常见的渠道:右键单击上下文菜单项;菜单键上下文菜单项;热键Ctrl + C。数据网格内容来自数据绑定,但由于复制命令是一个仅针对视图的操作,因此它完全在视图层中实现,而不是在视图模型中实现。所以我不使用iccommand,而只使用后面代码中的事件处理程序。
DataGrid的SelectionUnit被设置为FullRow,但是箭头导航键仍然有效,并且可以看到单个单元格的焦点矩形。因此,当选择整行时,可以聚焦单个单元格。对于这个命令,我需要确定聚焦的单元格。
菜单项已经相当复杂了。它的Click事件为我提供了MenuItem实例,从中我可以导航到ContextMenu并进一步导航到DataGrid。就是这样,没有点击单元格。我已经知道如何获得数据网格,一次只有一个是可见的。
我现在需要找出哪个单元格是聚焦的。但我甚至无法获得选定单元格或行甚至所有行的列表。我能找到的所有属性都指向信息的一些片段和DataGrid。行根本不存在。我可以在整个可视树中扫描一些集中的DataGridCell,但这可能不是很有效。
任何想法?
后来我还需要第二个函数"复制选定行到剪贴板",复制所有选定行的所有单元格的值,格式可以粘贴到Excel(制表符分隔行)。
辅助函数:
/// <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属性