下降目标如何检测取消的阻力&;加入WPF?

下降目标如何检测取消的阻力&;加入WPF?,wpf,drag-and-drop,Wpf,Drag And Drop,我试图编写一些通用代码来处理WPF drop目标中的dropAllowDrop设置为true,我已经在Drop目标元素上连接了DragEnter,DragOver,DragLeave,&Drop。使用冒泡事件可以嵌套放置目标 注意:我无法访问拖动源-这是应用程序间的拖放 如果在可能的删除结束时要执行一些UI清理,并且用户按Esc键取消删除,则删除目标似乎永远不会获得我可以区别于所有其他事件的特定事件。删除很容易,但什么表示取消 我的问题是: DragLeave是一个冒泡路由事件 e.Origi

我试图编写一些通用代码来处理WPF drop目标中的drop
AllowDrop
设置为true,我已经在Drop目标元素上连接了
DragEnter
DragOver
DragLeave
,&
Drop
。使用冒泡事件可以嵌套放置目标

注意:我无法访问拖动源-这是应用程序间的拖放

如果在可能的删除结束时要执行一些UI清理,并且用户按Esc键取消删除,则删除目标似乎永远不会获得我可以区别于所有其他事件的特定事件。删除很容易,但什么表示取消

我的问题是:

  • DragLeave
    是一个冒泡路由事件
  • e.OriginalSource
    始终通过hittesting为此事件(以及相应的预览)设置
  • 目标是一个
    ItemsControl
    (列表框是我目前测试的对象)
当我拖过预定的拖放目标时,我会从目标中的子视觉对象中获得大量的
DragLeave
事件。我从来没有从目标身上得到任何东西。网格、矩形、边框、文本块,它们都很乐意地发送给我
DragLeave
,但没有一个来自我连接到的实际
ItemsControl
。我认为这可能是一个命中测试问题,但我已经将
ItemsControl
的背景设置为颜色,这没有什么区别

我错过了什么?我该如何确定丢弃操作已经完成


(我试图解决的实际问题是,我在树状视图中实现了一些自定义的拖动行为,当您将鼠标悬停在文件夹上时,它会展开文件夹,并在拖放完成时取消计时器和撤消展开,等等,但我甚至无法为列表框合理地触发事件).

您确实有一个复杂的场景,因此这将从basic开始,希望为您提供一个方向和解决方案

只有当控件标记为AllowDrop=true时,框架才会通知DragEnter事件。所以确保你已经做到了。听起来你有,但我只是想确定一下

我不知道为什么需要DragLeave事件,但如果要获取所选数据,获取数据的最简单方法不是挂接到DragLeave,而是挂接到PreviewMouseMove。然后,在执行Dodragdop之前,您可以确定是否按下鼠标以及移动的距离

在这种情况下,您还可以添加和分析拖动数据。开始拖动时,您可以创建一个新的DataObject,并通过DoDragDrop调用发送它:

  private static void listBox_PreviewMouseMove(object sender, MouseEventArgs e)
  {
     // Get the current mouse position
     var mousePos = e.GetPosition(null);
     var diff = startPoint - mousePos;

     if (canScroll && e.LeftButton == MouseButtonState.Pressed &&
         (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
          Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
     {
        var dataObject = (from lbi in startList.Items.Cast<object>().Select((t, i) => (ListBoxItem)startList.ItemContainerGenerator.ContainerFromIndex(i)) where lbi != null && lbi.IsSelected select Convert.ToString(lbi.Content)).ToList();

        // Initialize the drag & drop operation
        var listBoxData = new ListBoxData(){ StartList = startList, Data = dataObject};
        var dragData = new DataObject("listBoxData", listBoxData);

        System.Windows.DragDrop.DoDragDrop(startList, dragData, DragDropEffects.Move);
     }
  }

我的建议是在拖动事件数据中添加一些独特的信息,以根据数据区分事件。您可以选择列表框中的数据项,也可以选择一个包含数据项和另一个指示器的新类(如果需要)。

您确实有一个复杂的场景,因此这将从basic开始,希望为您提供一个方向和解决方案

只有当控件标记为AllowDrop=true时,框架才会通知DragEnter事件。所以确保你已经做到了。听起来你有,但我只是想确定一下

我不知道为什么需要DragLeave事件,但如果要获取所选数据,获取数据的最简单方法不是挂接到DragLeave,而是挂接到PreviewMouseMove。然后,在执行Dodragdop之前,您可以确定是否按下鼠标以及移动的距离

在这种情况下,您还可以添加和分析拖动数据。开始拖动时,您可以创建一个新的DataObject,并通过DoDragDrop调用发送它:

  private static void listBox_PreviewMouseMove(object sender, MouseEventArgs e)
  {
     // Get the current mouse position
     var mousePos = e.GetPosition(null);
     var diff = startPoint - mousePos;

     if (canScroll && e.LeftButton == MouseButtonState.Pressed &&
         (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
          Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
     {
        var dataObject = (from lbi in startList.Items.Cast<object>().Select((t, i) => (ListBoxItem)startList.ItemContainerGenerator.ContainerFromIndex(i)) where lbi != null && lbi.IsSelected select Convert.ToString(lbi.Content)).ToList();

        // Initialize the drag & drop operation
        var listBoxData = new ListBoxData(){ StartList = startList, Data = dataObject};
        var dragData = new DataObject("listBoxData", listBoxData);

        System.Windows.DragDrop.DoDragDrop(startList, dragData, DragDropEffects.Move);
     }
  }

我的建议是在拖动事件数据中添加一些独特的信息,以根据数据区分事件。从列表框选择的数据项,或保存数据项和其他指示符的新类(如果需要)。

检查e.Source而不是e.OriginalSource,如果您在ItemsControl上设置了DropTarget=“True”&您将DropOver事件附加到ItemsControl,事件参数e.Source应该是ItemsControl。

如果您在ItemsControl上设置了DropTarget=“True”,并且将DropOver事件附加到ItemsControl,则检查是否为e.Source而不是e.OriginalSource,事件参数e.Source应该是ItemsControl。

不幸的是,这假设我是编写DoDragDrop部分的人。我只能影响正在接收丢弃的代码。如果我能把代码放在调用DoDragDrop的地方,我会从返回值中知道删除的结果(例如,用户按下Esc键,结果将是无),但不幸的是,该代码位位于另一个应用程序中:)在DragOver事件处理程序中,您是否尝试查看它是否包含任何数据?是-DragOver事件检查传入格式并相应设置效果。这是在特效被设置为“无”以外的情况下,因为这是一个所需的下降,即松开鼠标按钮将产生下降事件。如果发生拖放,我可以从拖放事件中清理UI;Esc取消是困扰我的一点。不幸的是,如果取消拖动,则不会产生任何问题。我唯一能想到的是在所有拖放事件中跟踪一个布尔值,然后在窗口或控件上处理PreviewKeyDown,查看在该布尔值为真时是否按了ESC。@Josh:但是,如果是“应用程序间拖放”,应用程序将不会被聚焦,即不会响应键盘事件,请看我的问题:不幸的是,这假设我是撰写DoDragDrop部分的人。我只能影响正在接收丢弃的代码。如果我能将代码放在调用DoDragDrop的地方,我就可以从返回值中知道删除的结果(例如,用户按下Esc键,则结果为“无”),但不幸的是,该代码位在另一个应用程序中