MVVM Light WPF拖放

时间:2014-07-25 20:13:59

标签: wpf drag-and-drop mvvm-light

我已经阅读了MVVM Light源代码,但似乎唯一的Drag and Drop示例处理从Windows中拖动文件。我有一个ListView,我希望每个ListViewItem能够在我的应用程序中拖动到另一个面板,以及从另一个面板接收drop。我找不到一个单一的实例或教程,关于在哪里做到这一点。我希望有人对此有所了解吗?

1 个答案:

答案 0 :(得分:2)

这是我的自定义多重选择TreeView的拖放行为,但我清理了代码,它必须与ListView完美配合

 public class DragAndDropBehavior<T> : Behavior<T> where T : ListView
{
    #region Fields

    private double tolerance = 20;
    private double offset = 5;
    private bool isDragging;
    private Point startPosition;

    #endregion Fields

    #region Properties
    public double Tolerance { get { return tolerance; } set { tolerance = value; } }
    public double Offset { get { return offset; } set { offset = tolerance; } }

    #endregion Properties

    #region Methods

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.MouseLeftButtonDown += AssociatedObjectOnMouseLeftButtonDown;
        AssociatedObject.MouseMove += AssociatedObjectOnMouseMove;
        AssociatedObject.DragOver += AssociatedObjectOnDragOver;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.MouseLeftButtonDown -= AssociatedObjectOnMouseLeftButtonDown;
        AssociatedObject.MouseMove -= AssociatedObjectOnMouseMove;
        AssociatedObject.DragOver -= AssociatedObjectOnDragOver;
    }

    #endregion Methods

    #region Handlers

    private void AssociatedObjectOnDragOver(object sender, DragEventArgs e)
    {
        var control = sender as ItemsControl;
        if (control == null)
            return;
        var scrollViewer = VisualTreeCustomHelper.FindVisualChild<ScrollViewer>(control);
        var verticalPos = e.GetPosition(control).Y;
        if (verticalPos < Tolerance)
        {
            scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - Offset);
        }
        if (verticalPos > control.ActualHeight - Tolerance)
        {
            scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + Offset);
        }
    }

    private bool IsDragStart(Point position)
    {
        return Math.Abs(position.X - startPosition.X) > SystemParameters.MinimumHorizontalDragDistance ||
                Math.Abs(position.Y - startPosition.Y) > SystemParameters.MinimumVerticalDragDistance;
    }

    private void AssociatedObjectOnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        startPosition = e.GetPosition(null);
    }

    private void AssociatedObjectOnMouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton != MouseButtonState.Pressed || isDragging || !IsDragStart(e.GetPosition(null)))
            return;
        isDragging = true;
        DragDrop.DoDragDrop(AssociatedObject, AssociatedObject.SelectedItem, DragDropEffects.Move);
        isDragging = false;
        }

    #endregion Handlers
}

这是帮助代码(它不是由我编写的)

public class VisualTreeCustomHelper
{
    public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject
    {
        // Search immediate children first (breadth-first)
        for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            var child = VisualTreeHelper.GetChild(obj, i);

            if (child is T)
                return (T)child;
            var childOfChild = FindVisualChild<T>(child);

            if (childOfChild != null)
                return childOfChild;
        }
        return null;
    }
}

现在你可以像这样处理drop事件了

private void ListView_OnDrop(object sender, DragEventArgs e)
{
    var droppedItem = e.Data.GetData(ListView.SelectedItem.GetType());
    var target = e.OriginalSource as UIElement;
    //Some operations with dropped item
}

如果需要,可以在行为中处理drop事件,并在那里对元素进行操作。

您可以阅读有关高级拖放行为的this tutorial