ItemsControl拖放

我有一个带有DataTemplate的ItemsControl,它绑定到整数的ObservableCollection。

       

并在Windows资源中:

      

我正在尝试实现在ItemsControl中拖放项目的能力(即能够重新排序整数)。 有没有人有一个如何做到这一点的简单例子? 我连接了PreviewMouseMove,DragEnter和Drop事件。 问题是我无法弄清楚如何确定拖动哪个项目以及拖动它的位置。 似乎整个ItemsControl都被传递到事件中。

这是我如何做到的一个例子。

XAML:

                  

视图模型:

  class MyViewModel { public MyViewModel() { MyCommand = new ICommandImplementation(); } public ObservableCollection MyData { get { return new ObservableCollection(new string[]{ "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "twenty" }); } } public ICommand MyCommand { get; private set; } private class ICommandImplementation : ICommand { public bool CanExecute(object parameter) { return true; } public event EventHandler CanExecuteChanged; public void Execute(object parameter) { System.Windows.MessageBox.Show("Button clicked! " + (parameter ?? "").ToString()); } } } 

事件:

  private void Drop(object sender, DragEventArgs e) { var source = e.Data.GetData("Source") as string; if (source != null) { int newIndex = listview.Items.IndexOf((sender as Button).Content); var list = listview.ItemsSource as ObservableCollection; list.RemoveAt(list.IndexOf(source)); list.Insert(newIndex, source); } } private void PreviewMouseMove(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed) { Task.Factory.StartNew(new Action(() => { Thread.Sleep(500); App.Current.Dispatcher.BeginInvoke(new Action(() => { if (e.LeftButton == MouseButtonState.Pressed) { var data = new DataObject(); data.SetData("Source", (sender as Button).Content); DragDrop.DoDragDrop(sender as DependencyObject, data, DragDropEffects.Move); e.Handled = true; } }), null); }), CancellationToken.None); } } 

上面的示例有点复杂,因为list中的每个项目都是一个Button然后在Button click我还需要执行一些操作。 你的情况相对容易。

对许多开发人员而言,拖放可能会令人困惑。 但下面是一些关键点如何做到这一点:

  1. 使用PreviewMouseMove事件实际开始拖动并在处理程序中使用DragDrop.DoDragDrop事件来引发DragDrop相关事件和Cursorssender参数是当前捕获鼠标的元素,在这种情况下是被拖动的UIElement

  2. 如果要更改Mouse当前拖动的元素的视觉效果,请使用DragEnterDragOver事件。 sender参数是当前拖动/刚刚结束拖动情境的元素。

  3. 使用Drop事件来处理被删除的元素。 sender参数是Drop发生的元素。

  4. 使用DataObject对象在这些事件之间传递信息。 该类的SetData方法用于在SetData添加数据。 此方法有两个参数,它们的作用类似于key-value对。 设置后,您可以通过将key作为参数传递,使用GetData方法在下一个DragDrop事件中获取此数据。 (即e.Data.GetData("Source")

这是一个相对的post。