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

时间:2010-01-19 15:10:55

标签: wpf drag-and-drop adorner

我正在使用一个装饰来显示被拖动元素的'幽灵'......

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 个答案:

答案 0 :(得分:6)

来自Bea Stollnitz的this(不幸的是仅作为缓存版本提供)相当古老的博客文章,它几乎涵盖了您的问题。它有一个很好的拖放实现,一个装饰显示“鬼影”。

基本上拖放WPF是一个非常复杂的过程 - 如果你想要一些自定义的DragAdorners - 涉及添加一堆附加的依赖属性来处理所涉及的所有事件的设置,特别是以不同的方式显示adorner不会干扰掉线代码。

Bea的代码通过在实际拖放操作之前设置一个帮助类来设置拥有Window的{​​{1}}事件处理程序和DragOver,这样就可以控制所有在实际拖动源和放置目标之间移动。

答案 1 :(得分:3)

所以,仔细观察Bea's code redoced指的是......

我仍然在顶级网格上设置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;
}

答案 2 :(得分:0)

我知道这是一个老问题,但是最近我问了同样的事情,然后不得不自己回答。我通过p / invoke使用hooks来获取本机窗口消息,然后再通过拖放操作消耗它们。这使我即使在拖放过程中也可以跟踪鼠标,而不必在我不希望的位置设置AllowDrop。

要获得完整答案(包括我使用的大多数代码),请查看我的问题:
WPF - Track mouse during Drag & Drop while AllowDrop = False