アプリケーションとウィンドウで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;
}