首页 文章

drop目标如何检测WPF中已取消的拖放?

提问于
浏览
1

我正在尝试编写一些通用代码来处理WPF丢弃目标中的丢弃 . AllowDrop 设置为true,我已经连接到放置目标UIElement上的 DragEnterDragOverDragLeaveDrop . 使用冒泡事件可以嵌套放置目标 .

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

如果我有一些UI清理要在潜在的丢弃结束时执行,并且用户按Esc取消掉落,则放置目标似乎永远不会得到一个特定的事件,我可以区别于所有其他事件 . 丢弃很容易,但什么表示取消?

我遇到的问题是:

  • DragLeave 是一个冒泡的路线事件 .
    始终通过命中测试为此事件(以及相应的预览)设置

  • e.OriginalSource .

  • 目标是 ItemsControl (列表框是我目前正在测试的) .

当我拖过我想要的放置目标时,我会从目标中的子视觉效果中获得大量的 DragLeave 事件 . 我从来没有从目标本身得到任何东西 . 网格,矩形,边框,文本块,它们都很高兴地发送给我 DragLeave ,但实际上没有一个'm connected up to. I thought it might be a hit-testing problem, but I'将 ItemsControl 的背景设置为一种颜色,它没有任何区别 .

我错过了什么?我怎么能确定放下操作已经完成了?

(我试图解决的实际问题是,我在TreeView中实现了一些自定义拖动行为,当您将鼠标悬停在文件夹上时会扩展文件夹,并在删除完成后取消计时器并取消扩展,以及更多内容,但我甚至无法为ListBox明智地触发事件 .

2 回答

  • 0

    你确实有一个复杂的场景,所以这将开始基本,希望给你一个方向,并希望有一个解决方案 .

    如果控件标记为AllowDrop = true,则框架将仅通知DragEnter事件 . 所以一定要确保你做到了 . 这听起来像你有,但我只是想确定 .

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

    在这种情况下,您还可以添加和分析拖动数据 . 拖动开始时,您可以创建一个新的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);
         }
      }
    

    现在可以通过使用DragEventArgs对象访问此拖动数据(如果不重命名事件参数,则为e):

    e.Data.GetData("listBoxData")
    

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

  • 0

    检查 e.Source 而不是e.OriginalSource,如果你在ItemsControl上设置DropTarget = "True"并且你有DropOver事件附加到ItemsControl,则事件参数e.Source应该是ItemsControl .

相关问题