我们在应用程序和窗口中使用MVVM模式,我们有两个TreeView
允许从第一个树中拖动项目并将其放在第二个树上。为了避免代码落后,我们使用行为来绑定对ViewModel的拖放。
该行为几乎实现like this example并且像魅力一样,只有一个错误。
该场景是一个比显示它的窗口大的树,因此它有一个垂直滚动条。当一个项目被选中并且用户想要滚动时,程序开始拖放(这会阻止实际滚动,因此不是我们想要的)。
由于滚动条包含在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;
}
答案 0 :(得分:4)
看看this implementation of Drag and Drop behaviour for ListView by Josh Smith。它有处理滚动条的代码和DnD的一些其他不明显的问题(如拖动阈值,精确的鼠标坐标等)。这种行为也可以很容易地用于TreeViews。
答案 1 :(得分: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>