Click here to Skip to main content
Licence 
First Posted 17 Jul 2003
Views 184,833
Downloads 3,060
Bookmarked 77 times

Drag and Drop ListView row reordering

By David Boland | 11 Nov 2003
This article presents a simple ListView control that provides row reordering using Drag and Drop.
1 vote, 3.2%
1
2 votes, 6.5%
2
2 votes, 6.5%
3
3 votes, 9.7%
4
23 votes, 74.2%
5
4.74/5 - 31 votes
3 removed
μ 4.42, σa 1.91 [?]

Introduction

An application I worked on required a mechanism whereby the user could rearrange the index of a row within a ListView control at runtime. For this, I wanted to use Drag and Drop, however after trailing through the Internet for some examples, I was unable to find something specific to C#, therefore I decided to implement my own.

Using the code

The ListView control presented here adds the property AllowRowReorder to the existing .NET ListView, which enables or disables the control's ability to reorder it rows.

In order to provide Drag and Drop support to the control, the methods OnItemDrag, OnDragEnter and OnDragDrop of the base control must be overridden. OnItemDrag is the method called once the control detects that a Drag and Drop operation has begun. It is here that any pre 'Drag and Drop' logic must be performed; this entails ensuring that row reordering has been enabled. Finally to inform the ListView that the Drag and Drop operation is valid, the DoDragDrop method is called, the first parameter being the Drag data, which identifies the object to be dragged and needs to be a String, Bitmap or a MetaFile. For the ListView provided, this is a hard-coded string, which will be used in the OnDragEnter method for Drop validation, since the items to be dragged will implicitly be the currently selected ListView items.

protected override void OnItemDrag(ItemDragEventArgs e)
{
  base.OnItemDrag(e);
  if(!this.AllowRowReorder)
  {
    return;
  }
  base.DoDragDrop(REORDER, DragDropEffects.Move);
}

The OnDragEnter validates whether or not the item being dragged, as identified by the DragEventArgs.Data object, can be dropped into the control. Note that when Drag and Drop is enabled within the control, it must provide logic to handle drag events from all drag enabled sources. The ListView provided simply ensures that the data passed matches the hard-coded value supplied by the OnItemDrag method.

protected override void OnDragEnter(DragEventArgs e)
{
  base.OnDragEnter(e);
  if(!this.AllowRowReorder)
  {
    e.Effect = DragDropEffects.None;
    return;
  }
  if(!e.Data.GetDataPresent(DataFormats.Text))
  {
    e.Effect = DragDropEffects.None;
    return;
  }
  String text = (String)e.Data.GetData(REORDER.GetType());
  if(text.CompareTo(REORDER)==0)
  {
    e.Effect = DragDropEffects.Move;
  }
  else
  {
    e.Effect = DragDropEffects.None; 
  }
}

Subsequently, OnDragOver ensures the continuing validity of the Drop operation as you move the mouse over the items in the control.

protected override void OnDragOver(DragEventArgs e)
{
  if(!this.AllowRowReorder)
  {
    e.Effect = DragDropEffects.None;
    return;
  }
  if(!e.Data.GetDataPresent(DataFormats.Text))
  {
    e.Effect = DragDropEffects.None;
    return;
  }
  Point cp = base.PointToClient(new Point(e.X, e.Y));
  ListViewItem hoverItem = base.GetItemAt(cp.X, cp.Y);
  if(hoverItem==null)
  {
    e.Effect = DragDropEffects.None;
    return;
  }
  foreach(ListViewItem moveItem in base.SelectedItems)
  {
    if(moveItem.Index==hoverItem.Index)
    {
        e.Effect = DragDropEffects.None;
        hoverItem.EnsureVisible();
        return;
    }
  }
  base.OnDragOver(e);
  String text = (String)e.Data.GetData(REORDER.GetType());
  if(text.CompareTo(REORDER)==0)
  {
    e.Effect = DragDropEffects.Move;
    hoverItem.EnsureVisible();
  }
  else
  {
    e.Effect = DragDropEffects.None;        
  }
}

Finally OnDragDrop performs the actual Drop operation, this includes identifying the ListViewItems to be moved and the row index they will be moved to. Notice that I’m assuming that the ListViewItems to be moved are the control's currently selected items.

protected override void OnDragDrop(DragEventArgs e)
{
  base.OnDragDrop(e);
  if(!this.AllowRowReorder)
  {
    return;
  }
  if(base.SelectedItems.Count==0)
  {
    return;
  }
  Point cp = base.PointToClient(new Point(e.X, e.Y));
  ListViewItem dragToItem = base.GetItemAt(cp.X, cp.Y);
  if(dragToItem==null)
  {
    return;
  }
  int dropIndex = dragToItem.Index;
  if(dropIndex>base.SelectedItems[0].Index)
  {
    dropIndex++;
  }
  ArrayList insertItems = 
    new ArrayList(base.SelectedItems.Count);
  foreach(ListViewItem item in base.SelectedItems)
  {
    insertItems.Add(item.Clone());
  }
  for(int i=insertItems.Count-1;i>=0;i--)
  {
    ListViewItem insertItem =
     (ListViewItem)insertItems[i];
    base.Items.Insert(dropIndex, insertItem);
  }
  foreach(ListViewItem removeItem in base.SelectedItems)
  {
    base.Items.Remove(removeItem);
  }
}

Downloads

Source and demo projects have been created using #Develop.

Update

  • 6th October 2003 - Fix for reordering problem when dragging multiple items.
  • 10 November 2003 – Updated for automatic scrolling during a Drag operation (suggestion from JayBarry and Brian Pierson)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

David Boland

Web Developer

United States United States

Member


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
QuestionI don't know how to use the listviewex PinmemberMember 474288813:33 30 Jun '11  
GeneralMy vote of 5 PinmemberBig D9:09 15 Feb '11  
GeneralDrag and Drop between groups Pinmemberesofter1:44 12 Oct '09  
Hello!
I have problem with drag and drop items between groups.
Index of items don't depend from groups and when I want to drag item to another group then items are being reordered in all groups.
How can I fix this problem?
QuestionDrag and Drop? Pinmembercodehack10:56 23 Apr '09  
Generalitems controls in a listview Pinmemberadsana0:23 14 Apr '09  
QuestionHow to use it with CheckedListBox Pinmembermilan.fratrik1:04 14 Jul '08  
GeneralListView control PinmemberPdeveloper6:05 27 Jun '08  
GeneralDoes not work inside a WPF UserControl inside a MMC 3.0 Container [modified] PinmemberAhead19994:11 22 Apr '08  
GeneralUsing the code Pinmembershamsteady9:12 9 Mar '07  
GeneralAfterRowReorder Event PinmemberTom Lawrance3:02 13 Oct '06  
GeneralAlternate method... Pinmembercamillo4:56 12 Jul '06  
GeneralRe: Alternate method... PinmemberPat Kujawa7:39 28 Apr '10  
GeneralDoesn´t works in View.LargeIcon mode Pinmemberemo_casares6:15 22 Apr '05  
GeneralRe: Doesn´t works in View.LargeIcon mode PinmemberDavid Boland5:40 25 Apr '05  
GeneralRe: Doesn´t works in View.LargeIcon mode Pinmemberuv5072:59 4 Oct '05  
GeneralRe: Doesn´t works in View.LargeIcon mode PinmemberDavid Boland1:55 6 Oct '05  
GeneralRe: Doesn´t works in View.LargeIcon mode Pinmemberaryxmyth7:36 8 Apr '06  
GeneralRe: Doesn´t works in View.LargeIcon mode [modified] PinmemberMilky Way22:43 18 Jun '06  
AnswerRe: Doesn´t works in View.LargeIcon mode Pinmemberntiagobr10:01 24 Oct '06  
QuestionScrolling within the listbox? PinmemberJayBarry8:17 29 Oct '03  
AnswerRe: Scrolling within the listbox? PinmemberJayBarry9:45 29 Oct '03  
GeneralRe: Scrolling within the listbox? PinmemberBrian Pierson5:54 10 Nov '03  
GeneralRe: Scrolling within the listbox? PinmemberDavid Boland6:44 10 Nov '03  
QuestionHow to sort rows as well as columns? PinmemberBakutotsu7:22 15 Oct '03  
AnswerRe: How to sort rows as well as columns? PinmemberDavid Boland23:57 15 Oct '03  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120210.1 | Last Updated 12 Nov 2003
Article Copyright 2003 by David Boland
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid