C# 在滚动时禁用拖放

C# 在滚动时禁用拖放,c#,wpf,drag-and-drop,scroll,treeview,C#,Wpf,Drag And Drop,Scroll,Treeview,我已经在WPF中为TreeView实现了拖放功能 所有工作正常,但当滚动显示在树状视图中时,如果我在树中选择一个项目,然后尝试滚动(垂直或水平),树状视图将尝试执行拖放操作 以下是源代码: class TreeViewRearranger { private TreeView mTreeView; private int MOVE_TOLERANCE = 10; private TreeViewItem mDraggedItem = null; private

我已经在WPF中为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;
    }
}
类TreeViewArranger
{
私人TreeView mTreeView;
私有int MOVE_公差=10;
私有TreeViewItem mDraggedItem=null;
私有TreeViewItem mTargetDrop=null;
私有DropAdorner mDropAdorner=null;
公共无效初始化(TreeView TreeView)
{
mTreeView=treeView;
SetupDragDropEvents();
}
专用void SetupDragDropEvents()
{
mTreeView.MouseDown+=mTreeView\u MouseDown;
mTreeView.MouseMove+=mTreeView\u MouseMove;
mTreeView.DragOver+=mTreeView\u DragOver;
mTreeView.Drop+=mTreeView\u Drop;
mTreeView.DragEnter+=mTreeView\u DragEnter;
mTreeView.DragLeave+=mTreeView\u DragLeave;
}
void mTreeView_MouseDown(对象发送器,鼠标按钮ventargs e)
{
if(例如ChangedButton!=鼠标按钮左)
返回;
mLastMouseDown=e.GetPosition(mTreeView);
}
void mTreeView\u MouseMove(对象发送方,MouseEventArgs e)
{
如果(例如LeftButton!=鼠标按钮状态已按下)
返回;
点currentPosition=e.GetPosition(mTreeView);

如果((Math.Abs(currentPosition.X-mLastMouseDown.X)您可能必须将自己附加到ScrollViewer ScrollChanged事件,并且在触发该事件时禁用拖放。我没有尝试过,但我认为这可能是一个尝试的起点

ScrollViewer scrollViewer = GetVisualChild<ScrollViewer>(mTreeView);
        scrollViewer.ScrollChanged += new ScrollChangedEventHandler(scrollViewer
ScrollViewer ScrollViewer=GetVisualChild(mTreeView);
scrollViewer.ScrollChanged+=新的ScrollChangedEventHandler(scrollViewer