如何在 WPF 拖放过程中更新拖动装饰器的位置?

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,直到我到达实际的放置目标。

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

3个回答

6

有一篇来自Bea Stollnitz的旧博客文章this(不幸的是只能使用缓存版本),非常详细地涵盖了您的问题。它具有漂亮的拖放实现,带有一个显示“幽灵图像”的装饰器。

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

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


3

因此,仔细查看Bea的代码,redoced提到的是...

我仍然在顶级网格上设置 AllowDrop="true" 并提供 DragOver 处理程序,以便我可以更新装饰器位置,但我也在这里将 DragDropEffects 设置为 None。 然后,我只需要向实际的拖放目标添加一个 DragOver 处理程序来更新装饰器位置...并确保设置 e.Handled = true,以便顶级网格的处理程序不会在我悬停在一个拖放目标上时将效果重置为 None ...

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

1
该链接现在已失效。 - Berin Loritsch

1
我知道这是一个老问题,但最近我遇到了同样的问题,然后不得不自己回答。我使用hooks通过p/invoke获取本地窗口消息,以便在它们被拖放操作消耗之前跟踪鼠标,而无需设置我不想要的AllowDrop。
有关完整答案(包括我使用的大部分代码),您可以查看我的问题:
WPF - Track mouse during Drag & Drop while AllowDrop = False

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接