在滚动条上的WPF TreeView中拖放

Mat*_*ten 8 c# wpf treeview drag-and-drop behavior

我们在我们的应用程序和窗口中使用MVVM模式,我们有两个TreeView允许从第一个树中拖动项目并将其放在第二个树上.为了避免代码落后,我们使用行为绑定对ViewModel的拖放.

该行为实现非常类似于此示例,并且像魅力一样工作,有一个错误.

场景是一个比显示它的窗口大的树,因此它有一个垂直滚动条.当选择一个项目并且用户想要滚动时,程序开始拖放(这会阻止实际滚动,因此不是我们想要的).

由于滚动条包含在TreeView控件中,因此这并不奇怪.但是我无法确定鼠标是否在滚动条上方.

TreeViewItems通过主题使用边框,面板等为代表,所以一个简单的InputHitTest并不像人们想象的那么简单.

有没有人遇到过同样的问题?

如果需要更多代码覆盖问题,我可以粘贴.xaml中的一些行.


编辑

合并Nikolays链接我使用IsMouseOverScrollbar方法解决了问题,如果将来有人遇到此问题,必须通过以下方式更改上面的代码:

private static void PreviewMouseMove(object sender, MouseEventArgs e)
{
    if (e.LeftButton != MouseButtonState.Pressed || startPoint == null)
        return;

    if (!HasMouseMovedFarEnough(e))
        return;

   if (IsMouseOverScrollbar(sender, e.GetPosition(sender as IInputElement)))
   {
       startPoint = null;
       return;
   }

   var dependencyObject = (FrameworkElement)sender;
   var dataContext = dependencyObject.GetValue(FrameworkElement.DataContextProperty);
   var dragSource = GetDragSource(dependencyObject);

   if (dragSource.GetDragEffects(dataContext) == DragDropEffects.None)
        return;

   DragDrop.DoDragDrop(
            dependencyObject, dragSource.GetData(dataContext), dragSource.GetDragEffects(dataContext));
}


    private static bool IsMouseOverScrollbar(object sender, Point mousePosition)
    {
        if (sender is Visual)
        {
            HitTestResult hit = VisualTreeHelper.HitTest(sender as Visual, mousePosition);

            if (hit == null) return false;

            DependencyObject dObj = hit.VisualHit;
            while(dObj != null)
            {
                if (dObj is ScrollBar) return true;

                if ((dObj is Visual) || (dObj is Visual3D)) dObj = VisualTreeHelper.GetParent(dObj);
                else dObj = LogicalTreeHelper.GetParent(dObj);
            }
        }

        return false;
    }
Run Code Online (Sandbox Code Playgroud)

Nik*_*lay 4

看一下Josh Smith 对 ListView 的拖放行为的实现。它有代码来处理滚动条和 DnD 的其他一些不明显的问题(如拖动阈值、精确的鼠标坐标等)。这种行为也可以很容易地应用于 TreeViews。