WPFのTreeViewにドラッグアンドドロップ機能を実装しました。
すべて正常に機能しますが、スクロールがツリービューに表示されているときに、ツリー内のアイテムを選択してからスクロール(垂直または水平)しようとすると、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;
    }
}