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