views:

919

answers:

4

OK, first for context look at the Windows desktop; You can take items (folders, files) on the desktop and drag them around to different places and they "stay" where you dragged them. This seems to be a pretty useful feature to offer users so as to allow them to create their own "groupings" of items.

My question is thus: Is there a control in .NET that approximates this behavior with a collection of items?

I'm thinking something like a listview in "LargeIcon" mode, but it allows you to drag the icons around to different places inside the control.

+1  A: 

I think the closest would the ListView control, but even that is more like an explorer window. You might be able to create your own view that does what you want, but you'd need to manually persist icon locations somewhere.

Joel Coehoorn
Thanks; I meant to write list*view* not list*box*...but I don't think a ListView lets you drag the items around inside of it, does it?
BKimmel
The Windows desktop icon interface is in fact a Windows ListView control written in unmanaged code (C or C++).
David Grant
+1  A: 

If you are not opposed to using WPF, Josh Smith has created a pretty neat canvas that I am currently using for a project. It allows you to add controls and drag them around the canvas. You would have to handle what is loaded on the canvas and where on the next load of the program, but that is pretty simple. http://www.codeproject.com/KB/WPF/DraggingElementsInCanvas.aspx

Totty
+1  A: 

This depends on whether this is a windows application or a web browser based application. In either case you need to have some sort of container to manage the locations of controls. You can manage the position of controls inside of a container with their X and Y coordinates.

You would handle the actual movement using the drag events. So you have drag start, while dragging (you might show a place holder graphic or change the cursor), and finally a drag end (set the control's x and y to the new position). Obviously these aren't the actual event names, but a search for "how to handle drag events" should get you started.

In a web environment, I know jquery has dragging capability built in. So you might want to look at that. The one big thing you'll have to be careful of is maintaining the positions of your controls between postbacks. I'm not sure what would happen in this case.

Haydar
+3  A: 

You can do this with a standard ListView control by implementing drag-and-drop. Here's a sample control that does this:

using System;
using System.Drawing;
using System.Windows.Forms;

public class MyListView : ListView {
  private Point mItemStartPos;
  private Point mMouseStartPos;

  public MyListView() {
    this.AllowDrop = true;
    this.View = View.LargeIcon;
    this.AutoArrange = false;
    this.DoubleBuffered = true;
  }

  protected override void OnDragEnter(DragEventArgs e) {
    if (e.Data.GetData(typeof(ListViewItem)) != null) e.Effect = DragDropEffects.Move;
  }
  protected override void OnItemDrag(ItemDragEventArgs e) {
    // Start dragging
    ListViewItem item = e.Item as ListViewItem;
    mItemStartPos = item.Position;
    mMouseStartPos = Control.MousePosition;
    this.DoDragDrop(item, DragDropEffects.Move);
  }
  protected override void OnDragOver(DragEventArgs e) {
    // Move icon
    ListViewItem item = e.Data.GetData(typeof(ListViewItem)) as ListViewItem;
    if (item != null) {
      Point mousePos = Control.MousePosition;
      item.Position = new Point(mItemStartPos.X + mousePos.X - mMouseStartPos.X,
          mItemStartPos.Y + mousePos.Y - mMouseStartPos.Y);
    }
  }
}
Hans Passant
awesome.. Thanks, dude.
BKimmel
Note, this only works with .NET 2.0. Moreover, you don't need the InteropServices. Strip out OnHandleCreated() and CreateParams() and add to constructor this.AutoArrange = false; and this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);.
AMissico
Clever
AMissico