9

アプリケーションとウィンドウでMVVMパターンを使用しているTreeViewので、最初のツリーからアイテムをドラッグして2番目のツリーにドロップできる2つのがあります。コードビハインドを回避するために、ビヘイビアーを使用して、ViewModelに対してドラッグアンドドロップをバインドしています。

動作はこの例のように実装され、1つのバグがあり、チャームのように機能します。

シナリオは、それを表示しているウィンドウよりも大きいツリーであるため、垂直スクロールバーがあります。アイテムが選択され、ユーザーがスクロールしたい場合、プログラムはドラッグアンドドロップを開始します(これにより実際のスクロールが妨げられるため、私たちが望むものではありません)。

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

JoshSmithによる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 に答える