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