我在Canvas上有一个拖放操作,当一个对象被拖入和拖出时,它应该做某事。我的问题是DragEnter / DragLeave事件在鼠标移动对象时继续触发,而不仅仅是在进入/退出时。鼠标移动得越快,事件就越频繁。
Canvas DragOver事件移动了DraggedObject的Canvas.Top/Left,我认为这可能是我的问题,但我不知道如何解决这个问题。
答案 0 :(得分:17)
以下是事件序列:
DragEnter
事件。DragEnter
处理程序移动Panel,使其现在位于鼠标下方。由于鼠标不再位于Canvas上(它位于Panel上方),DragLeave
事件将触发。移动鼠标的速度越快,您收到的事件就越多。
你的问题的本质是拖放使用命中测试,并且通过移动你的面板,你正在击败命中测试的能力,看看你的面板“后面”知道它被丢弃的容器。
解决方案是使用您自己的代码进行拖放处理,这实际上并不困难。 WPF的命中测试引擎足够强大,可以在当前对象后面进行命中测试,但拖放功能不会使用此功能。您可以直接使用它,但需要使用VisualTreeHelper.HitTest
和HitTestFilterCallback
的{{1}}重载。只需传递一个过滤器,忽略被拖动面板中的任何命中。
我发现对于你描述的场景,通过处理鼠标事件进行拖放实际上比使用内置的DoDragDrop更容易,因为你不必处理复杂性(DataObject,DragDropEffects,QueryContinueDrag等) )。这种额外的复杂性对于启用应用程序和进程之间的拖动方案非常重要,但对您正在做的事情没有帮助。
以下是简单的解决方案:
享受。
答案 1 :(得分:2)
这有点旧,但我有同样的问题。我正在使用一个装饰器来指示被拖动的东西被拖到哪里。我会在DragEnter
中启用该装饰,然后立即注册DragLeave
并停用该装饰,然后DragEnter
...
IsEnabled = false
对我不起作用,但IsHitTestVisible = false
做了。我把它放在我的装饰者的构造函数中,现在一切都很好用了:
public DragDropAdorner(UIElement adornedElement) : base(adornedElement)
{
_layer = AdornerLayer.GetAdornerLayer(AdornedElement);
_layer.IsEnabled = false;
_layer.IsHitTestVisible = false;
}
答案 2 :(得分:2)
我最近有一个类似的问题,尽管它在Angular 6框架中,使用了反应形式。这是我针对自己的情况解决的方法:
基本上,我在拖动时关闭了该组件上的更改检测。
import { ChangeDetectorRef } from '@angular/core';
constructor(private chngDetRef: ChangeDetectorRef) { //...
private onDragStart(event, dragSource, dragIndex) {
// ...
this.chngDetRef.detach();
// ...
private onDrop(event, dragSource, dragIndex) {
// ...
this.chngDetRef.reattach();
// ...
private onDragEnd(event, dragIndex) {
// ...
this.chngDetRef.reattach();
// ...
如果您有很多父级或分层组件,则可能还必须对它们的更改检测进行一些操作才能看到实质性的改进。
祝你好运!
答案 3 :(得分:0)
我发现有必要为正在发生的事情添加更准确的答案,我也会在与此问题相关的其他问题中添加相同的答案。
好的,这就是发生的事情:
解决方案:
确保您在鼠标下绘制的元素为IsEnabled=false
。
这样它就不会捕获拖放操作,也不会产生闪烁效果。
答案 4 :(得分:0)
我遇到了类似的问题,而解决该问题的魔力是e.Handled = true;
当要在其上拖动某些东西时,我想选择一个TabItem。这是我的解决方法。
在资源字典中定义:
<Style TargetType="TabItem">
<Setter Property="AllowDrop" Value="True" />
<EventSetter Event="DragEnter" Handler="tabDragEnter" />
<EventSetter Event="DragOver" Handler="tabDragOver" />
</Style>
然后使用tabDragEnter处理程序:
private void tabDragEnter(object sender, DragEventArgs e)
{
TabItem m_TabItem = sender as TabItem;
m_TabItem.IsSelected = true;
}
最后是tabDragOver处理程序:
private void tabDragOver(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}