WPF C#: Rearrange items in listbox via drag and drop

前端 未结 7 1086
你的背包
你的背包 2020-11-27 12:08

I am trying to figure out how to move the items in a pre-populated listbox up and down via mouse drags.

I have looked at the Control.DoDragDrop method from microsof

7条回答
  •  眼角桃花
    2020-11-27 13:01

    Using dnr3's answers I have created version with fixed selection issues.

    Window1.xaml

    
        
            
        
    
    

    Window1.xaml.cs

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace ListBoxReorderDemo
    {
        public class Item
        {
            public string Name { get; set; }
            public Item(string name)
            {
                this.Name = name;
            }
        }
    
        public partial class Window1 : Window
        {
            private Point _dragStartPoint;
    
            private T FindVisualParent(DependencyObject child)
                where T : DependencyObject
            {
                var parentObject = VisualTreeHelper.GetParent(child);
                if (parentObject == null)
                    return null;
                T parent = parentObject as T;
                if (parent != null)
                    return parent;
                return FindVisualParent(parentObject);
            }
    
            private IList _items = new ObservableCollection();
    
            public Window1()
            {
                InitializeComponent();
    
                _items.Add(new Item("1"));
                _items.Add(new Item("2"));
                _items.Add(new Item("3"));
                _items.Add(new Item("4"));
                _items.Add(new Item("5"));
                _items.Add(new Item("6"));
    
                listBox.DisplayMemberPath = "Name";
                listBox.ItemsSource = _items;
    
                listBox.PreviewMouseMove += ListBox_PreviewMouseMove;
    
                var style = new Style(typeof(ListBoxItem));
                style.Setters.Add(new Setter(ListBoxItem.AllowDropProperty, true));
                style.Setters.Add(
                    new EventSetter(
                        ListBoxItem.PreviewMouseLeftButtonDownEvent,
                        new MouseButtonEventHandler(ListBoxItem_PreviewMouseLeftButtonDown)));
                style.Setters.Add(
                        new EventSetter(
                            ListBoxItem.DropEvent, 
                            new DragEventHandler(ListBoxItem_Drop)));
                listBox.ItemContainerStyle = style;
            }
    
            private void ListBox_PreviewMouseMove(object sender, MouseEventArgs e)
            {
                Point point = e.GetPosition(null);
                Vector diff = _dragStartPoint - point;
                if (e.LeftButton == MouseButtonState.Pressed &&
                    (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
                        Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
                {
                    var lb = sender as ListBox;
                    var lbi = FindVisualParent(((DependencyObject)e.OriginalSource));
                    if (lbi != null)
                    {
                        DragDrop.DoDragDrop(lbi, lbi.DataContext, DragDropEffects.Move);
                    }
                }
            }
            private void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
            {
                _dragStartPoint = e.GetPosition(null);
            }
    
            private void ListBoxItem_Drop(object sender, DragEventArgs e)
            {
                if (sender is ListBoxItem)
                {
                    var source = e.Data.GetData(typeof(Item)) as Item;
                    var target = ((ListBoxItem)(sender)).DataContext as Item;
    
                    int sourceIndex = listBox.Items.IndexOf(source);
                    int targetIndex = listBox.Items.IndexOf(target);
    
                    Move(source, sourceIndex, targetIndex);
                }
            }
    
            private void Move(Item source, int sourceIndex, int targetIndex)
            {
                if (sourceIndex < targetIndex)
                {
                    _items.Insert(targetIndex + 1, source);
                    _items.RemoveAt(sourceIndex);
                }
                else
                {
                    int removeIndex = sourceIndex + 1;
                    if (_items.Count + 1 > removeIndex)
                    {
                        _items.Insert(targetIndex, source);
                        _items.RemoveAt(removeIndex);
                    }
                }
            }
        }
    }
    

    Version with support for generics and data binding.

    Window1.xaml

    
        
            
                
                    
                        
                    
                
            
        
    
    

    Window1.xaml.cs

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace ListBoxReorderDemo
    {
        public class DragAndDropListBox : ListBox 
            where T : class
        {
            private Point _dragStartPoint;
    
            private P FindVisualParent

    (DependencyObject child) where P : DependencyObject { var parentObject = VisualTreeHelper.GetParent(child); if (parentObject == null) return null; P parent = parentObject as P; if (parent != null) return parent; return FindVisualParent

    (parentObject); } public DragAndDropListBox() { this.PreviewMouseMove += ListBox_PreviewMouseMove; var style = new Style(typeof(ListBoxItem)); style.Setters.Add(new Setter(ListBoxItem.AllowDropProperty, true)); style.Setters.Add( new EventSetter( ListBoxItem.PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(ListBoxItem_PreviewMouseLeftButtonDown))); style.Setters.Add( new EventSetter( ListBoxItem.DropEvent, new DragEventHandler(ListBoxItem_Drop))); this.ItemContainerStyle = style; } private void ListBox_PreviewMouseMove(object sender, MouseEventArgs e) { Point point = e.GetPosition(null); Vector diff = _dragStartPoint - point; if (e.LeftButton == MouseButtonState.Pressed && (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance)) { var lb = sender as ListBox; var lbi = FindVisualParent(((DependencyObject)e.OriginalSource)); if (lbi != null) { DragDrop.DoDragDrop(lbi, lbi.DataContext, DragDropEffects.Move); } } } private void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { _dragStartPoint = e.GetPosition(null); } private void ListBoxItem_Drop(object sender, DragEventArgs e) { if (sender is ListBoxItem) { var source = e.Data.GetData(typeof(T)) as T; var target = ((ListBoxItem)(sender)).DataContext as T; int sourceIndex = this.Items.IndexOf(source); int targetIndex = this.Items.IndexOf(target); Move(source, sourceIndex, targetIndex); } } private void Move(T source, int sourceIndex, int targetIndex) { if (sourceIndex < targetIndex) { var items = this.DataContext as IList; if (items != null) { items.Insert(targetIndex + 1, source); items.RemoveAt(sourceIndex); } } else { var items = this.DataContext as IList; if (items != null) { int removeIndex = sourceIndex + 1; if (items.Count + 1 > removeIndex) { items.Insert(targetIndex, source); items.RemoveAt(removeIndex); } } } } } public class Item { public string Name { get; set; } public Item(string name) { this.Name = name; } } public class ItemDragAndDropListBox : DragAndDropListBox { } public partial class Window1 : Window { private IList _items = new ObservableCollection(); public Window1() { InitializeComponent(); _items.Add(new Item("1")); _items.Add(new Item("2")); _items.Add(new Item("3")); _items.Add(new Item("4")); _items.Add(new Item("5")); _items.Add(new Item("6")); listBox.DataContext = _items; } } }

提交回复
热议问题