Click here to Skip to main content
15,860,972 members
Articles / Programming Languages / C#
Article

Drag and Drop ListView row reordering

Rate me:
Please Sign up or sign in to vote.
4.67/5 (40 votes)
11 Nov 20032 min read 328.3K   15.8K   95   36
This article presents a simple ListView control that provides row reordering using Drag and Drop.

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.

C#
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.

C#
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.

C#
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.

C#
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


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionInsertionMark ?... Pin
Member 1036751016-Oct-16 6:28
Member 1036751016-Oct-16 6:28 
thanks for your coding i was try to add Insertion i could not ?

can you help me how to reordering with INSERTION mark ?

Thanks
PraiseNice. Good Job Pin
Member 1193117425-Jul-16 3:09
Member 1193117425-Jul-16 3:09 
GeneralMy vote of 1 Pin
Trần Hùng Cường4-Mar-14 22:24
Trần Hùng Cường4-Mar-14 22:24 
GeneralA vrey nice and relatively simple enhancement to the ListView control, thanks Pin
Member 187983216-Sep-13 11:46
Member 187983216-Sep-13 11:46 
QuestionI don't know how to use the listviewex Pin
Member 474288830-Jun-11 12:33
Member 474288830-Jun-11 12:33 
GeneralMy vote of 5 Pin
eyedia15-Feb-11 8:09
eyedia15-Feb-11 8:09 
GeneralDrag and Drop between groups Pin
esofter12-Oct-09 0:44
esofter12-Oct-09 0:44 
QuestionDrag and Drop? Pin
codehack23-Apr-09 9:56
codehack23-Apr-09 9:56 
Generalitems controls in a listview Pin
adsana13-Apr-09 23:23
adsana13-Apr-09 23:23 
QuestionHow to use it with CheckedListBox Pin
milan.fratrik14-Jul-08 0:04
milan.fratrik14-Jul-08 0:04 
GeneralListView control Pin
Pdeveloper27-Jun-08 5:05
Pdeveloper27-Jun-08 5:05 
GeneralDoes not work inside a WPF UserControl inside a MMC 3.0 Container [modified] Pin
Ahead199922-Apr-08 3:11
Ahead199922-Apr-08 3:11 
GeneralUsing the code Pin
shamsteady9-Mar-07 8:12
shamsteady9-Mar-07 8:12 
GeneralAfterRowReorder Event Pin
Tom Lawrance13-Oct-06 2:02
professionalTom Lawrance13-Oct-06 2:02 
GeneralAlternate method... Pin
camillo12-Jul-06 3:56
camillo12-Jul-06 3:56 
GeneralRe: Alternate method... Pin
Pat Kujawa28-Apr-10 6:39
Pat Kujawa28-Apr-10 6:39 
GeneralRe: Alternate method... Pin
BillWoodruff21-Mar-13 6:49
professionalBillWoodruff21-Mar-13 6:49 
GeneralDoesn´t works in View.LargeIcon mode Pin
emo_casares22-Apr-05 5:15
emo_casares22-Apr-05 5:15 
GeneralRe: Doesn´t works in View.LargeIcon mode Pin
David Boland25-Apr-05 4:40
David Boland25-Apr-05 4:40 
GeneralRe: Doesn´t works in View.LargeIcon mode Pin
uv5074-Oct-05 1:59
uv5074-Oct-05 1:59 
GeneralRe: Doesn´t works in View.LargeIcon mode Pin
David Boland6-Oct-05 0:55
David Boland6-Oct-05 0:55 
GeneralRe: Doesn´t works in View.LargeIcon mode Pin
aryxmyth8-Apr-06 6:36
aryxmyth8-Apr-06 6:36 
GeneralRe: Doesn´t works in View.LargeIcon mode [modified] Pin
Milky Way18-Jun-06 21:43
Milky Way18-Jun-06 21:43 
AnswerRe: Doesn´t works in View.LargeIcon mode Pin
ntiagobr24-Oct-06 9:01
ntiagobr24-Oct-06 9:01 
QuestionScrolling within the listbox? Pin
JayBarry29-Oct-03 7:17
JayBarry29-Oct-03 7:17 

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

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