在尝试了很多事情之后,我想我想出了一个方法来做到这一点。 DragOver 和 Drop 事件向您发送 DragEventArgs 参数。你用它来做命中测试。但是,如果您进行了测试,则不太可能直接击中您想要的项目。相反,您将遇到构成项目模板一部分的内容。要找到您感兴趣的 TreeViewItems,您可以尝试沿着 Visual Tree 向上走。
在此示例中,顶级 TreeViewItems 绑定到 GroupItem 实例,子节点绑定到 DragItems 实例。 tv 是 TreeView 元素本身的名称。在这段代码中,假设我会找到它是安全的,因为事件处理程序是在这个元素上定义的。
我创建了以下沿着树向上走的代码。
private void FindDropTarget(
out TreeViewItem pGroupingNode,
out TreeViewItem pItemNode,
DragEventArgs pDragEventArgs)
{
pItemNode = null;
pGroupingNode = null;
DependencyObject k = VisualTreeHelper.HitTest(tv, pDragEventArgs.GetPosition(tv)).VisualHit;
while (k != null)
{
if (k is TreeViewItem)
{
TreeViewItem treeNode = k as TreeViewItem;
if (treeNode.DataContext is GroupItem)
{
pGroupingNode = treeNode;
}
else if (treeNode.DataContext is DragItems)
{
pItemNode = treeNode;
}
}
else if (k == tv)
{
Console.WriteLine("Found treeview instance");
return;
}
k = VisualTreeHelper.GetParent(k);
}
}
像这样消费它。请注意检查IsVisible,这很重要:
private void tv_DragOver(object sender, DragEventArgs e)
{
TreeViewItem groupingNode, itemNode;
FindDropTarget(out groupingNode, out itemNode, e);
GroupItem groupingData = (groupingNode != null ? groupingNode.DataContext as GroupItem : null);
DragItems dragItem = (itemNode != null && itemNode.IsVisible ? itemNode.DataContext as DragItems : null);
Console.WriteLine("Hovering ...");
Console.WriteLine(
"Grouping Node = {0}, Item Node = {1}",
groupingData != null ? groupingData.Title : "null",
dragItem != null ? dragItem.Id : "null");
}
如果您想对物品掉落的位置提供某种视觉指示,请考虑使用像 Bea Stollnitz explains here 这样的装饰器。您还可以考虑更改 Bound 数据类上的某种值(例如具有可以通过数据绑定突出显示项目的 IsHovering 属性)