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