3

我正在使用装饰器来显示被拖动元素的“幽灵”......

var adornerLayer = AdornerLayer.GetAdornerLayer(topLevelGrid);
dragAdorner = new DragAdorner(topLevelGrid, itemToDrag);
adornerLayer.Add(dragAdorner);
dragAdorner.UpdatePosition(e.GetPosition(topLevelGrid));

DragDrop.DoDragDrop(sourceItems, viewModel, DragDropEffects.Move);

adornerLayer.Remove(dragAdorner);
itemToDrag = null;

...但我找不到在拖动过程中更新装饰器位置的好方法。我最接近的是通过设置AllowDrop="true"顶级网格并给它一个 DragOver 处理程序......

private void TopLevelGrid_OnDragOver(object sender, DragEventArgs e)
{
 dragAdorner.UpdatePosition(e.GetPosition(topLevelGrid));
}

但这意味着我没有得到DragDropEffects关于光标的正确反馈,即它总是显示DragDropEffects.Move光标而不是DragDropEffects.None直到我超过实际的放置目标。

有谁知道更新装饰器位置的更好方法?

4

3 回答 3

6

Bea Stollnitz有 这篇(不幸的是只能作为缓存版本提供)相当古老的博客文章,它几乎涵盖了您的问题。它有一个很好的拖放实现,带有一个显示“幽灵图像”的装饰器。

基本上WPF中的拖放是一个相当复杂的过程——如果你想要一些自定义的DragAdorners——涉及添加一堆附加的依赖属性来处理所有涉及的事件的设置,特别是以不干扰的方式显示装饰器与删除代码。

Bea 的代码通过一个帮助类来工作,该类在实际拖放操作之前设置 owneringWindowDragOver事件处理程序,这样您就可以控制实际拖放源和拖放目标之间的所有移动。AllowDrop

于 2010-01-20T22:39:18.553 回答
3

所以,仔细看看Bea 的代码,redoded 指的是......

我仍然AllowDrop="true"在顶层网格上设置并给它一个 DragOver 处理程序,我可以在其中更新装饰器位置,但我还在此处将 DragDropEffects 设置为 None。然后我只需将 DragOver 处理程序添加到实际放置目标以更新装饰器位置......并确保设置e.Handled = true为顶级网格的处理程序不会在我结束时将效果设置回无一个下降目标...

private void TopLevelGrid_OnDragOver(object sender, DragEventArgs e)
{
 UpdateDragAdornerPosition(e.GetPosition(topLevelGrid));
 e.Effects = DragDropEffects.None;
 e.Handled = true;
}

private void DropTarget_OnDragOver(object sender, DragEventArgs e)
{
 UpdateDragAdornerPosition(e.GetPosition(topLevelGrid));
 e.Handled = true;
}
于 2010-01-21T09:25:31.547 回答
1

我知道这是一个老问题,但我最近问了同样的问题,然后不得不自己回答。我通过 p/invoke 使用钩子在本地窗口消息被拖放操作消耗之前获取它们。这让我即使在拖放过程中也能跟踪鼠标,而无需在我不想要的地方设置 AllowDrop。

有关完整答案(包括我使用的大部分代码),您可以查看我的问题:
WPF - Track mouse during Drag & Drop while AllowDrop = False

于 2019-08-08T23:03:22.593 回答