先上效果图:
关键代码:
1 public partial class Window1 : System.Windows.Window 2 { 3 ListViewDragDropManager<Task> dragMgr; 4 ListViewDragDropManager<Task> dragMgr2; 5 6 public Window1() 7 { 8 InitializeComponent(); 9 this.Loaded += Window1_Loaded; 10 } 11 12 #region Window1_Loaded 13 14 void Window1_Loaded( object sender, RoutedEventArgs e ) 15 { 16 // Give the ListView an ObservableCollection of Task 17 // as a data source. Note, the ListViewDragManager MUST 18 // be bound to an ObservableCollection, where the collection's 19 // type parameter matches the ListViewDragManager's type 20 // parameter (in this case, both have a type parameter of Task). 21 ObservableCollection<Task> tasks = Task.CreateTasks(); 22 this.listView.ItemsSource = tasks; 23 24 this.listView2.ItemsSource = new ObservableCollection<Task>(); 25 26 // This is all that you need to do, in order to use the ListViewDragManager. 27 this.dragMgr = new ListViewDragDropManager<Task>( this.listView ); 28 this.dragMgr2 = new ListViewDragDropManager<Task>( this.listView2 ); 29 30 // Turn the ListViewDragManager on and off. 31 this.chkManageDragging.Checked += delegate { this.dragMgr.ListView = this.listView; }; 32 this.chkManageDragging.Unchecked += delegate { this.dragMgr.ListView = null; }; 33 34 // Show and hide the drag adorner. 35 this.chkDragAdorner.Checked += delegate { this.dragMgr.ShowDragAdorner = true; }; 36 this.chkDragAdorner.Unchecked += delegate { this.dragMgr.ShowDragAdorner = false; }; 37 38 // Change the opacity of the drag adorner. 39 this.sldDragOpacity.ValueChanged += delegate { this.dragMgr.DragAdornerOpacity = this.sldDragOpacity.Value; }; 40 41 // Apply or remove the item container style, which responds to changes 42 // in the attached properties of ListViewItemDragState. 43 this.chkApplyContStyle.Checked += delegate { this.listView.ItemContainerStyle = this.FindResource( "ItemContStyle" ) as Style; }; 44 this.chkApplyContStyle.Unchecked += delegate { this.listView.ItemContainerStyle = null; }; 45 46 // Use or do not use custom drop logic. 47 this.chkSwapDroppedItem.Checked += delegate { this.dragMgr.ProcessDrop += dragMgr_ProcessDrop; }; 48 this.chkSwapDroppedItem.Unchecked += delegate { this.dragMgr.ProcessDrop -= dragMgr_ProcessDrop; }; 49 50 // Show or hide the lower ListView. 51 this.chkShowOtherListView.Checked += delegate { this.listView2.Visibility = Visibility.Visible; }; 52 this.chkShowOtherListView.Unchecked += delegate { this.listView2.Visibility = Visibility.Collapsed; }; 53 54 // Hook up events on both ListViews to that we can drag-drop 55 // items between them. 56 this.listView.DragEnter += OnListViewDragEnter; 57 this.listView2.DragEnter += OnListViewDragEnter; 58 this.listView.Drop += OnListViewDrop; 59 this.listView2.Drop += OnListViewDrop; 60 } 61 62 #endregion // Window1_Loaded 63 64 #region dragMgr_ProcessDrop 65 66 // Performs custom drop logic for the top ListView. 67 void dragMgr_ProcessDrop( object sender, ProcessDropEventArgs<Task> e ) 68 { 69 // This shows how to customize the behavior of a drop. 70 // Here we perform a swap, instead of just moving the dropped item. 71 72 int higherIdx = Math.Max( e.OldIndex, e.NewIndex ); 73 int lowerIdx = Math.Min( e.OldIndex, e.NewIndex ); 74 75 if( lowerIdx < 0 ) 76 { 77 // The item came from the lower ListView 78 // so just insert it. 79 e.ItemsSource.Insert( higherIdx, e.DataItem ); 80 } 81 else 82 { 83 // null values will cause an error when calling Move. 84 // It looks like a bug in ObservableCollection to me. 85 if( e.ItemsSource[lowerIdx] == null || 86 e.ItemsSource[higherIdx] == null ) 87 return; 88 89 // The item came from the ListView into which 90 // it was dropped, so swap it with the item 91 // at the target index. 92 e.ItemsSource.Move( lowerIdx, higherIdx ); 93 e.ItemsSource.Move( higherIdx - 1, lowerIdx ); 94 } 95 96 // Set this to 'Move' so that the OnListViewDrop knows to 97 // remove the item from the other ListView. 98 e.Effects = DragDropEffects.Move; 99 } 100 101 #endregion // dragMgr_ProcessDrop 102 103 #region OnListViewDragEnter 104 105 // Handles the DragEnter event for both ListViews. 106 void OnListViewDragEnter( object sender, DragEventArgs e ) 107 { 108 e.Effects = DragDropEffects.Move; 109 } 110 111 #endregion // OnListViewDragEnter 112 113 #region OnListViewDrop 114 115 // Handles the Drop event for both ListViews. 116 void OnListViewDrop( object sender, DragEventArgs e ) 117 { 118 if( e.Effects == DragDropEffects.None ) 119 return; 120 121 Task task = e.Data.GetData( typeof( Task ) ) as Task; 122 if( sender == this.listView ) 123 { 124 if( this.dragMgr.IsDragInProgress ) 125 return; 126 127 // An item was dragged from the bottom ListView into the top ListView 128 // so remove that item from the bottom ListView. 129 (this.listView2.ItemsSource as ObservableCollection<Task>).Remove( task ); 130 } 131 else 132 { 133 if( this.dragMgr2.IsDragInProgress ) 134 return; 135 136 // An item was dragged from the top ListView into the bottom ListView 137 // so remove that item from the top ListView. 138 (this.listView.ItemsSource as ObservableCollection<Task>).Remove( task ); 139 } 140 } 141 142 #endregion // OnListViewDrop 143 144 }