George Shepherd's Windows Forms FAQ
Questions and answers in this FAQ have been collected from newsgroup posts, various mailing lists and the employees of Syncfusion.

19. Windows Forms ListBox

WinForms FAQ Home
   19.1 How do I add and delete items from a ListBox?
   19.2 How do I implement Drag and Drop support between ListBoxes?
   19.3 How can I drag file names from Windows Explorer and drop them into a listbox?
   19.4 How do I implement an ownerdrawn listbox?
   19.5 How can I set the width of a listbox to fit the text?



19.1 How do I add and delete items from a ListBox?


Check out Devinder Arora's article Using ListBox Control in C# on C# Corner.


19.2 How do I implement Drag and Drop support between ListBoxes?


The code below minimally handles D&D for a single selection list box by handling four events. The D&D is initiated in MouseDown if the user mouses down on the current selection. The DragEnter event is used to set the dragging effect to copy if you are not over the drag source. The DragDrop event is used to do the drop. And finally, the SelectedIndexChanged event is used to track the current selection for use in the MouseDown event. You can download a working project (C#, VB). This project handles additional events to provide visual queues during the drop.

The samples referenced above do not allow dragging and dropping within the same listbox. Here is another set of samples that does allow you to drag and drop within the same listbox.

public class ListBoxDragNDrop : ListBox
{
     private int lastMouseUpItemIndex = -1;
     private bool isDropSource = false;

     public ListBoxDragNDrop()
     {
          this.AllowDrop = true;     //allow D&D
          this.SelectionMode = SelectionMode.One;      //single selection

          DragDrop += new System.Windows.Forms.DragEventHandler(OnDragDrop);
          DragEnter += new System.Windows.Forms.DragEventHandler(OnDragEnter);
          MouseDown += new System.Windows.Forms.MouseEventHandler(OnMouseDown);
          SelectedIndexChanged += new System.EventHandler(OnSelectedIndexChanged);
     }
               
     private void OnDragDrop(object sender, DragEventArgs e)
     {
          if(e.Effect == DragDropEffects.Copy)
          {
               Point point = this.PointToClient(new Point(e.X, e.Y));
               int index = this.IndexFromPoint(point);
               if( index > -1 && index < this.Items.Count)
                    Items.Insert(index, e.Data.GetData(DataFormats.Text));
               else
                    Items.Add(e.Data.GetData(DataFormats.Text));
          }
     }

     private void OnDragEnter(object sender, System.Windows.Forms.DragEventArgs e)
     {
          if (e.Data.GetDataPresent(DataFormats.Text) && !isDropSource )
               e.Effect = DragDropEffects.Copy;
          else
               e.Effect = DragDropEffects.None;
     }

     private void OnMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
     {
          if(MouseButtons == MouseButtons.Left && SelectedIndex == lastMouseUpItemIndex)
          {
               isDropSource = true;
               DoDragDrop(SelectedItem, DragDropEffects.Copy);
               isDropSource = false;
               lastMouseUpItemIndex = this.SelectedIndex;
          }
     }

     private void OnSelectedIndexChanged(object sender, System.EventArgs e)
     {
          lastMouseUpItemIndex = this.SelectedIndex;
     }
}

One more note. If your listboxes contain full file pathnames, you can support dropping these paths onto Windows Explorer by supporting the FileDrop dataformat. In the OnMouseDown override, if you replace the DoDragDrop line with the following code block, you will be able to drop files.

     //put the file path is a string array
     string[] files = new String[1];
     files[0] = SelectedItem.ToString();

     //create a dataobject holding this array as a filedrop
     DataObject data = new DataObject(DataFormats.FileDrop, files);

     //also add the selection as textdata
     data.SetData(DataFormats.StringFormat, SelectedItem.ToString());

     //do the dragdrop
     DoDragDrop(data, DragDropEffects.Copy);


19.3 How can I drag file names from Windows Explorer and drop them into a listbox?


Change the control's Anchor property so that it is anchored on all 4 sides.



Please note that you can only have 1 control per form anchored in this manner (all 4 sides). And other controls on the form should be anchored by their sides that are not adjacent to special control anchored on all 4 sides.


19.4 How do I implement an ownerdrawn listbox?


Check out this sample project at gotnetdot.com. It derives from Form and implements the owner drawing by handling the DrawItem event and MeasureItem event.

You can also download a sample that implements an owner drawn listbox by deriving from ListBox and overriding the virtual methods OnDrawItem and OnMeasureItem. Here is a OnDrawItem override that draws colored rectangles in the listbox.

protected override void OnDrawItem(System.Windows.Forms.DrawItemEventArgs e)
{
     //undo the selection rect on the old selection
     if( oldSelectedRect != e.Bounds &&
          oldSelectedIndex > -1 && oldSelectedIndex < Items.Count)
     {
          e.Graphics.DrawRectangle(new Pen((Color) Items[oldSelectedIndex], 2), oldSelectedRect);
     }

     //draw the item .. here we just fill a rect
     if( e.Index > -1 && e.Index < Items.Count)
          e.Graphics.FillRectangle(new SolidBrush( (Color)Items[e.Index] ), e.Bounds);
     
     //draw selection rect if needed
     if(SelectedIndex == e.Index)
     {
          e.Graphics.DrawRectangle(new Pen(Color.Black,2), e.Bounds);
          oldSelectedRect = e.Bounds;
          oldSelectedIndex = e.Index;
     }
}



19.5 How can I set the width of a listbox to fit the text?


You can subclass ComboBox. In your derived class, make sure you set

     this.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
     this.DropDownStyle = ComboBoxStyle.DropDownList;

You also need to handle the DrawItem event to actually implement the drawing. Check out the details in the OwnerDrawnComboBox sample.

© 2001-2010 Copyright Syncfusion Inc. All rights reserved.  |  Privacy Policy  |  Contact  |  Sitemap