我们在我们的应用程序和窗口中使用 MVVM 模式,我们有两个TreeView
s 允许从第一个拖动项目并将其放在第二个树上。为了避免代码落后,我们使用行为来绑定 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;
}