7

I'm trying to implement a C# drag and drop row-reorder with a listview which would then update an SQL database with the current order of the rows. I've come across some snippets of code on the internet (one from this website which implemented a 'var' class) but none seem to be working with my needs. I don't need help updating the database as I have a good idea how I'd do this, but can't seem to get the row reordering to work correctly, any input would be appreciated.

-thanks

m&a

Mike
  • 73
  • 1
  • 1
  • 3

2 Answers2

15
  1. Ensure that AllowDragDrop is set to true.

  2. Implement handlers for at least these 3 events

    private void myList_ItemDrag(object sender, ItemDragEventArgs e)
        {
            DoDragDrop(e.Item, DragDropEffects.Link);
        }
    
        private void myList_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Link;
        }
    
        private void myList_DragDrop(object sender, DragEventArgs e)
        {
            // do whatever you need to reorder the list.
        }
    

    Getting the index of the row you dropped onto may look something like:

    Point cp = myList.PointToClient(new Point(e.X, e.Y));
    ListViewItem dragToItem = myList.GetItemAt(cp.X, cp.Y);
    int dropIndex = dragToItem.Index;
    
double-beep
  • 5,031
  • 17
  • 33
  • 41
Matthew Vines
  • 27,253
  • 7
  • 76
  • 97
  • Thanks, it looks like the method myList_DragDrop will require some tinkering. So to my understanding we're going to have to remove the selected item from the list, and later re-add it to the new index (where we want to drop it?). Plus, we'd also have to shift down the row that we drop into by one...is there an event that handles this? – Mike Jul 26 '10 at 14:08
  • Hi, the ItemDrag method passes in the entire ListView control into the DragDrog method, in which I am unable to grab the specific item which I've started dragging, any suggestions? private void empList_ItemDrag(object sender, ItemDragEventArgs e) { DoDragDrop(e.Item, DragDropEffects.Link); empList.Items.RemoveAt(empList.SelectedIndices[0]); } private void empList_DragDrop(object sender, DragEventArgs e) { Point cp = empList.PointToClient(new Point(e.X, e.Y)); ListViewItem dragToItem = empList.GetItemAt(cp.X, cp.Y); int dropIndex = dragToItem.Index; } – Mike Jul 26 '10 at 16:25
  • I asked a similar question about finding the correct index to insert the item, looks like it is the same approach but has some bug :( http://stackoverflow.com/questions/10759567/hoveritem-returing-null-in-listview – Bohn May 25 '12 at 18:34
  • [Manual reordering of items inside a ListView](http://www.codeproject.com/Articles/14487/Manual-reordering-of-items-inside-a-ListView) - Good CodeProject article on the subject – Andrina Websdale Feb 12 '13 at 16:15
0

I know this isn't ListView specific, but I have sample code for implementing row drag and drop out of / into a DataGridView. Some of it is obviously control specific, other code is actually pretty generic (such as deciding when its a drag):

http://adamhouldsworth.blogspot.com/2010/01/datagridview-multiple-row-drag-drop.html

Completely forgot the fact that ListView already allows drag-dropping!

I can also add some theory - when the drop occurs on your control, you will need to hit test on those coordinates (likely a method called HitTest) on the ListView to see what row was hit, this is the basis for where to insert the row being dragged.

Unrelated - is that var class perhaps the new var keyword in C#?

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
  • Hi Adam, We thought ListView allows drag-dropping however besides the property allowdrop = true, we can not find any automagic logic that moves the rows around for us. Which is why it looks like implementing it with events (like the post above) is what is required. The var attribute came into question when we looked at the following post: http://stackoverflow.com/questions/643275/c-drag-drop-in-listview – Mike Jul 26 '10 at 14:12
  • @Mike yea I realised when I spotted the other post, hence I struck out the relevant part of my answer. What I didn't realise was that the ListView has a GetItemAt method - encapsulating the hit test nicely for you. Using that, all that was needed was to remove the row and insert it at the given index - 1. Also, in that post is the new var keyword - just means the compiler infers the type for you - syntactic sugar. – Adam Houldsworth Jul 26 '10 at 14:24
  • Hi, the ItemDrag method passes in the entire ListView control into the DragDrog method, in which I am unable to grab the specific item which I've started dragging, any suggestions? private void empList_ItemDrag(object sender, ItemDragEventArgs e) { DoDragDrop(e.Item, DragDropEffects.Link); empList.Items.RemoveAt(empList.SelectedIndices[0]); } private void empList_DragDrop(object sender, DragEventArgs e) { Point cp = empList.PointToClient(new Point(e.X, e.Y)); ListViewItem dragToItem = empList.GetItemAt(cp.X, cp.Y); int dropIndex = dragToItem.Index; } – Mike Jul 26 '10 at 15:16
  • I think this comment would be best against Matthew Vines' answer. – Adam Houldsworth Jul 26 '10 at 16:00