9

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

该行为的实现与此示例非常相似,并且像魅力一样工作,只有一个错误。

场景是一棵比显示它的窗口大的树,因此它有一个垂直滚动条。When an item is selected and the user wants to scroll, the program starts drag and drop (which prevents the actual scrolling and therefore isn't what we want).

这并不奇怪,因为滚动条包含在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;
    }
4

2 回答 2

4

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

于 2012-04-16T09:01:32.297 回答
0

我有同样的问题。我通过将 TreeView 放在 ScrollViewer 中解决了这个问题。

<ScrollViewer Grid.Column="0">
  <TreeView BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MouseMove="DeviceTree_OnMouseMove" PreviewMouseLeftButtonDown="DeviceTree_OnPreviewMouseLeftButtonDown" Name="DeviceTree" ItemsSource="{Binding Devices}"/>
</ScrollViewer>
于 2016-11-11T12:42:36.100 回答