我有一个标签控件,可以让我将标签项拖出我的应用程序 这个拖动将打开一个新窗口,它将跟随鼠标,直到我释放鼠标左键 还可以将选项卡项拖回到源选项卡控件中,并将其重新附加到其前父级或任何其他能够理解拖动数据的控件。
private static void DragOutTabControl_PreviewQueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
e.Handled = true;
if (DragControlIsHit)
{
if (_previewWindow != null && _previewWindow.IsVisible)
{
_previewWindow.Clear();
_previewWindow.Hide();
}
}
else
{
if (_previewWindow == null)
{
_previewWindow = new PreviewWindow();
_previewWindow.SetData();
}
_previewWindow.Left = CursorPos.X - 15;
_previewWindow.Top = CursorPos.Y - 15;
_previewWindow.Show();
}
}
我现在遇到的问题是,当预览窗口跟随鼠标时,它位于光标正下方
这样,源窗口控件的dragEnter和dragOver事件不会触发,因为窗口阻止了命中测试
即使我在窗口中将IsHitTestVisible设置为false,也会阻止点击测试,同时拖放仍处于活动状态。
将IsEnabled设置为false并将背景更改为null没有任何效果。
public PreviewWindow()
{
Background = null;
IsEnabled = false;
IsHitTestVisible = false;
}
是否有可能在任何命中测试中隐藏预览窗口,或者手动将命中测试传递给拖动窗口后面的任何控件?
编辑,更多信息来解决我的问题:
我不仅要将标签项拖出我的标签控件并为它们打开新窗口,而且我还希望能够将其他标签项拖动到现有的拖出窗口中。
此外,应该可以将标签项拖回原始标签控件。
所有这一切都运行得很好,除了唯一的问题是我无法通过拖放测试来隐藏预览窗口。
答案 0 :(得分:2)
Rachel的答案绝对正确,我建议任何人使用普通的MouseEvents而不是DragDropEvents。
但是由于我的应用程序中有几个窗口涉及拖动,我不得不想出一个不同的解决方案:
private static void ProcessDraggedHitTest(
Window window)
{
var CursorPos = GetCursorPos();
var MousePosition = Mouse.GetPosition(window);
IDragTarget hitControl = null;
var hitTestResult = VisualTreeHelper.HitTest(window, new Point(CursorPos.X + MousePosition.X, CursorPos.Y + MousePosition.Y));
if (hitTestResult != null)
{
var parent = hitTestResult.VisualHit as DependencyObject;
while (parent != null)
{
hitControl = parent as IDragTarget;
if (tileOutControl != null)
break;
else
parent = VisualTreeHelper.GetParent(parent);
}
if (hitControl != null)
DragOver(hitControl, _draggedItem);
}
}
其中DragOver(hitControl,_draggedItem)是当DragEnter或DragOver事件触发时通常调用的函数,而GetCursorPos()是Win32调用以获取正确的鼠标位置。
现在你必须以正确的z顺序为所有窗口调用这些函数,你就完成了。
我希望我可以帮助我的解决方案,但如果有人发现更好的方法,我很有兴趣听到它。
答案 1 :(得分:1)
我对DragDrop
事件命中测试提出了类似的问题,我收到的the answer是切换到使用MouseEvents
而不是DragDrop
事件。我做了转换,从不后悔,也没有尝试过回到WPF的内置DragDrop事件。
作为替代方案,如果您不想使用鼠标事件,则可以在Adorner Layer而不是UI层上显示您的窗口,并且只有在Drop事件发生后才将其呈现为新对象。