Drag and Drop Reordering of ListView Items in C#
For a C# project I’m working on I wanted to implement a ListView control in a Windows Form. After some extensive Googling and searching through some cruddy examples on CodeProject and the like, I finally stumbled across what I needed under the MSDN documentation for the ListView.InsertionMark Property.
There’s no easy way to find that article (unless, like me, you end up just reading the documentation for every ListView property until you stumble on the right one) so I figured I’d post what I came up with here in case some future soul found it useful.
First of all, we’ve got to take care of the events necessary to handle the drag and drop:
ItemDrag
// handle the ListView's ItemDrag event
private void myListView_ItemDrag(object sender, ItemDragEventArgs e)
{
myListView.DoDragDrop(e.Item, DragDropEffects.Move);
}
DragEnter
// handle the ListView's DragEnter event
private void myListView_DragEnter(object sender, DragEventArgs e)
{
e.Effect = e.AllowedEffect;
}
DragOver
// handle the ListView's DragOver event
private void myListView_DragOver(object sender, DragEventArgs e)
{
Point targetPoint =
myListView.PointToClient(new Point(e.X, e.Y));
int targetIndex = myListView.InsertionMark.NearestIndex(targetPoint);
// Confirm that the mouse pointer is not over the dragged item.
if (targetIndex > -1)
{
// Determine whether the mouse pointer is above or
// below of the midpoint of the closest item and set
// the InsertionMark.AppearsAfterItem property accordingly.
Rectangle itemBounds = myListView.GetItemRect(targetIndex);
if ( targetPoint.Y > itemBounds.Top + (itemBounds.Height / 2) )
{
myListView.InsertionMark.AppearsAfterItem = true;
}
else
{
myListView.InsertionMark.AppearsAfterItem = false;
}
}
// Set the location of the insertion mark. If the mouse is
// over the dragged item, the targetIndex value is -1 and
// the insertion mark disappears.
myListView.InsertionMark.Index = targetIndex;
}
Finishing touches
That’s essentially it. Of course, you’ll have to associate those methods with the appropriate events for your ListView control and edit as necessary. I modified the MSDN example to check whether the InsertionMark should be above or below the target item, rather than to the left or right as they had it, because I wanted to use the ListView to display a two-column list whose rows could be reordered. Also, this code will only work for single item selections (set MultiSelect to false on your ListView).
However, there is one more caveat that I found out the hard way and is the real reason for this post. The drag and drop re-ordering, in it’s current state, will not work on Windows XP (or earlier), even with the latest .NET framework installed.
The InsertionMark feature for .NET controls is provided by the same library that provides operating system themes, so any code using InsertionMarks won’t work unless the current environment has OSFeature.Themes present. You can check for this before setting the AllowDrop property of your list view like so:
if (OSFeature.Feature.IsPresent(OSFeature.Themes))
{
myListView.AllowDrop = true;
}
But the OSFeature.Feature.IsPresent(OSFeature.Themes) check will always return false unless your application has already called the Application.EnableVisualStyles() method. This should be called in your program’s Main() method, right before the Application.Run statement.
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(new ListViewInsertionMarkExample());
}
Now, you should be set under any version of Windows that can run your program.
hi there fantastic little web site you have there ;) I work with the very same template on my own blog however for whatever nutty explanation it appears to reload more rapid on this blog although your own features considerably more content. Have you been employing any specific plug ins or widgets that speed it up? Do you think you might be able to write about the widgets so maybe I might use these on my personal websites so twilight new moon followers could watch twilight breaking dawn online trailers and videos more quickly I would be grateful – many thanks ahead of time :)
Well, I have WP Super Cache installed, which is a plug-in I would recommend for everyone using WordPress. It will cache your pages and posts so they are able to load with less database round-trips. In short, it will make your WordPress site faster. :)
You can download it here: http://ocaoimh.ie/wp-super-cache/