I had google'd this pretty good. Figured out my own solution. Wrote it up for others to check out.
It's at http://www.urona.com/drag.htm. The good stuff is as follows: struct rDrag { internal bool Gone; // user dragged OFF the appropriate drop- control internal bool On; // we're dragging internal int Index; } rDrag mDragIt; // don't forget to set .AllowDrop on the ListView ... private void It_MouseDown(object sender, MouseEventArgs e) { if ((mDragIt.Gone) || (mDragIt.Index < 0)) try { ListViewItem Item = It.HitTest(e.X, e.Y).Item; // on MouseDown, X,Y is relative if (Item != null) { mDragIt.Index = Item.Index; mDragIt.Gone = false; mDragIt.On = false; } // .On only if .MouseMove } catch (ArgumentOutOfRangeException ex) { } // for .HitTest } private void It_MouseMove(object sender, MouseEventArgs e) { if ((!mDragIt.On) && (mDragIt.Index >= 0)) { mDragIt.On = true; It.DoDragDrop(mDragIt.Index, DragDropEffects.Move); } } // because MouseDown sets mDragIt.Index, and MouseMove initiates .DoDragDrop, the data passed is ignored as follows private void It_DragOver(object sender, DragEventArgs e) { if (mDragIt.Index >= 0) try { ListViewItem Item = It.HitTest(It.PointToClient(new Point(e.X, e.Y))).Item; // X,Y is absolute if ((Item != null) && (Item.Index != mDragIt.Index) && (Item.Index != (mDragIt.Index + 1))) { e.Effect = DragDropEffects.Move; } else { e.Effect = DragDropEffects.None; } } catch (ArgumentOutOfRangeException ex) { e.Effect = DragDropEffects.None; } // for .HitTest } private void It_DragDrop(object sender, DragEventArgs e) { if (mDragIt.Index >= 0) try { ListViewItem Item = It.HitTest(lvRoute.PointToClient(new Point (e.X, e.Y))).Item; // X,Y is absolute if ((Item != null) && (Item.Index != mDragIt.Index) && (Item.Index != (mDragIt.Index + 1))) { // however you wanna handle this ... mDragIt.Index is what was dragged ... Item.Index is the drop } } finally { mDragIt.Index = -1; mDragIt.On = false; } } private void lvRoute_DragLeave(object sender, EventArgs e) { mDragIt.Gone = true; // bad user ... off the reservation } // this is important ... it allows us to start a new drag-drop despite the fact mDragIt.Index >= 0 private void lvRoute_DragEnter(object sender, DragEventArgs e) { mDragRoute.Gone = false; // ah good ... they came back }
