滚动时禁用拖放

我已经在WPF中为TreeView实现了拖放function。

一切正常但是当滚动显示在树视图中时,如果我在树中选择一个项目,然后尝试滚动(垂直或水平),TreeView会尝试执行拖放操作。

这是源代码:

class TreeViewRearranger { private TreeView mTreeView; private int MOVE_TOLERANCE = 10; private TreeViewItem mDraggedItem = null; private TreeViewItem mTargetDrop = null; private DropAdorner mDropAdorner = null; public void Initialize(TreeView treeView) { mTreeView = treeView; SetupDragDropEvents(); } private void SetupDragDropEvents() { mTreeView.MouseDown += mTreeView_MouseDown; mTreeView.MouseMove += mTreeView_MouseMove; mTreeView.DragOver += mTreeView_DragOver; mTreeView.Drop += mTreeView_Drop; mTreeView.DragEnter += mTreeView_DragEnter; mTreeView.DragLeave += mTreeView_DragLeave; } void mTreeView_MouseDown(object sender, MouseButtonEventArgs e) { if (e.ChangedButton != MouseButton.Left) return; mLastMouseDown = e.GetPosition(mTreeView); } void mTreeView_MouseMove(object sender, MouseEventArgs e) { if (e.LeftButton != MouseButtonState.Pressed) return; Point currentPosition = e.GetPosition(mTreeView); if ((Math.Abs(currentPosition.X - mLastMouseDown.X) <= MOVE_TOLERANCE) && (Math.Abs(currentPosition.Y - mLastMouseDown.Y) <= MOVE_TOLERANCE)) return; StartDrag(); } void mTreeView_DragLeave(object sender, DragEventArgs e) { RemoveAdorners(); } void mTreeView_DragEnter(object sender, DragEventArgs e) { AdornerLayer layer = AdornerLayer.GetAdornerLayer(mTreeView); mDropAdorner = new DropAdorner(mTreeView); layer.Add(mDropAdorner); } private Point mLastMouseDown; private void StartDrag() { mDraggedItem = mTreeView.SelectedItem as TreeViewItem; if (mDraggedItem == null) return; DragDropEffects finalDropEffect = DragDrop.DoDragDrop( mTreeView, mTreeView.SelectedValue, DragDropEffects.Move); // Check that target is not null and item is // dragging(moving) if ((finalDropEffect != DragDropEffects.Move) || (mTargetDrop == null)) return; // A Move drop was accepted if (mDraggedItem.Header.ToString().Equals(mTargetDrop.Header.ToString())) return; PerformDragDrop(mDraggedItem, mTargetDrop); mTargetDrop = null; mDraggedItem = null; } private void PerformDragDrop(TreeViewItem source, TreeViewItem destination) { if (source == null || destination == null) return; OnRearrange(source, destination); } private static TreeViewItem GetParentTreeViewItem(DependencyObject item) { if (item == null) return null; DependencyObject parent = VisualTreeHelper.GetParent(item); TreeViewItem parentTreeViewItem = parent as TreeViewItem; return parentTreeViewItem ?? GetParentTreeViewItem(parent); } private void OnRearrange(TreeViewItem source, TreeViewItem destination) { if (source == null || destination == null) return; TreeNode sourceNode = source.Tag as TreeNode; TreeNode destinationNode = destination.Tag as TreeNode; TreeNode targetNode = destinationNode; if (!destination.IsExpanded || destination.Items.Count == 0) { TreeViewItem parentItem = GetParentTreeViewItem(destination); if (parentItem == null) { targetNode = mTreeView.Tag as TreeNode; } else { targetNode = parentItem.Tag as TreeNode; } } int index = targetNode.Children.IndexOf(destinationNode) + 1; // performed a rearrange from sourceNode to targetNode at index } void mTreeView_DragOver(object sender, DragEventArgs e) { Point currentPosition = e.GetPosition(mTreeView); if ((Math.Abs(currentPosition.X - mLastMouseDown.X) <= MOVE_TOLERANCE) && (Math.Abs(currentPosition.Y - mLastMouseDown.Y) <= MOVE_TOLERANCE)) return; // Verify that this is a valid drop and then store the drop target TreeViewItem item = GetNearestContainer(e.OriginalSource as UIElement); if (CheckDropTarget(mDraggedItem, item)) { e.Effects = DragDropEffects.Move; UpdateDropAdorner(item); } else { e.Effects = DragDropEffects.None; UpdateDropAdorner(null); } e.Handled = true; } void mTreeView_Drop(object sender, DragEventArgs e) { e.Effects = DragDropEffects.None; e.Handled = true; // Verify that this is a valid drop and then store the drop target TreeViewItem targetItem = GetNearestContainer (e.OriginalSource as UIElement); if (targetItem == null || mDraggedItem == null) return; mTargetDrop = targetItem; e.Effects = DragDropEffects.Move; UpdateDropAdorner(mTargetDrop); RemoveAdorners(); } private void UpdateDropAdorner(TreeViewItem targetItem) { mDropAdorner.UpdateTargetPosition(targetItem); } private TreeViewItem GetNearestContainer(UIElement element) { // Walk up the element tree to the nearest tree view item. TreeViewItem container = element as TreeViewItem; while ((container == null) && (element != null)) { element = VisualTreeHelper.GetParent(element) as UIElement; container = element as TreeViewItem; } return container; } private bool CheckDropTarget(TreeViewItem sourceItem, TreeViewItem targetItem) { if (sourceItem == null || targetItem == null) return false; if (sourceItem.Header.ToString().Equals(targetItem.Header.ToString())) return false; if (targetItem.IsDescendantOf(sourceItem)) return false; return true; } private void RemoveAdorners() { AdornerLayer layer = AdornerLayer.GetAdornerLayer(mTreeView); layer.Remove(mDropAdorner); mDropAdorner = null; } } 

您可能必须将自己附加到滚动查看器ScrollChanged事件,并在触发该事件时禁用拖放操作。 我没试过,但我认为这可能是一个尝试的起点

 ScrollViewer scrollViewer = GetVisualChild(mTreeView); scrollViewer.ScrollChanged += new ScrollChangedEventHandler(scrollViewer