简体   繁体   中英

How to implement Drag and Drop

I am working on a project. It does with drag and drop this is the code I have right now.

   namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void listBox1_MouseDown(object sender, MouseEventArgs e)
        {
            listBox1.DoDragDrop(listBox1.SelectedItem.ToString(), DragDropEffects.Move);
        }

        private void listBox2_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = e.AllowedEffect;
        }

        private void listBox2_DragDrop(object sender, DragEventArgs e)
        {
            listBox2.Items.Add(e.Data.GetData(DataFormats.Text));
            listBox1.Items.Remove(listBox1.SelectedItem.ToString());
        }

It lets you add to the second list box but I am trying to get it where you can also move the item back to first listbox if you want to. Do I repeat the code for the second list box as I did for the first one or is there a line of code I could just add.Also how can you tell if your program is “unbreakable”. Thanks.

For the main question of implementing drag & drop: yes, you would need to create handlers for listbox1 and listbox2 that mirror the functionality you already have:

  • A MouseDown event handler for listBox2
  • A DragEnter handler for listBox1
  • A DragDrop handler for listBox1.

Also you'd need to make sure you assign these handlers to be used for their respective events in the form designer.

Do I repeat the code for the second list box

Pretty much, yeah. Although you can simplify it a bit since the code will be essentially identical by having both listboxes use the same handler for MouseDown, DragEnter and DragDrop and then use the sender to figure out whether it's listBox1 or listBox2.

Also, you might want to think about your MouseDown handler. Most users won't expect a single click to immediately start a drag operation. Usually you would look for the mouse down and then for a mouse move while the button is down before starting the drag.

What I usually do is something like this:

private Size dragSize = SystemInformation.DragSize;
private Rectangle dragBounds = Rectangle.Empty;

private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
   if (e.Button == MouseButtons.Left)
   {
        dragBounds = new Rectangle(new Point(e.X - dragSize.Width / 2, e.Y - dragSize.Height/2), dragSize);
   }
   else
   {
       dragBounds = Rectangle.Empty;
   }
}

private void listBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left && dragBounds != Rectangle.Empty && !dragBounds.Contains(e.X, e.Y))
    {
        //start drag
        listBox1.DoDragDrop(listBox1.SelectedItem.ToString(), DragDropEffects.Move);
        dragBounds = Rectangle.Empty;
    }
}

You could reapeat the code, but I tend to not want to do that. Yours is an edge case; lots of methods that only have one line in them. But any time I see repetition in code, it signals to me that I need to pull that code out somewhere else. If the repetition is in the same class, move it to its own method on the class. If the repetition is in separate classes, either find another class outside the two where it makes sense to put the new method, or consider creating a new class that both classes can share. In your case, if I decided to move the code, I would do something like this:

private void listBox1_MouseDown(object sender, MouseEventArgs e)
{
    HandleMouseDown(listbox1);
}

private void listBox2_DragEnter(object sender, DragEventArgs e)
{
    HandleDragEnter( e );
}

private void listBox2_DragDrop(object sender, DragEventArgs e)
{
    HandleDragDrop( listBox1, listBox2, e );
}

private void listBox2_MouseDown(object sender, MouseEventArgs e)
{
    HandleMouseDown(listBox2);
}

private void listBox1_DragEnter(object sender, DragEventArgs e)
{
    HandleDragEnter( e );
}

private void listBox1_DragDrop(object sender, DragEventArgs e)
{
    HandleDragDrop( listBox2, listBox1, e );
}


private void HandleMouseDown( ListBox listBox )
{
    listBox.DoDragDrop(listBox.SelectedItem.ToString(), DragDropEffects.Move);
}

private void HandleDragEnter( DragEventArgs e )
{
    e.Effect = e.AllowedEffect;
}

private void HandleDragDrop( ListBox src, ListBox dst, DragEventArgs e )
{
    dst.Items.Add( e.Data.GetData(DataFormats.Text) );
    src.Items.Remove( src.SelectedItem.ToString() );
}

The advantage to moving the code is, if those methods grow to more than one line, you can change them in only one place. Of course, for a one line method, I would also remember that I can always move it to its own method later. My personal preference would be to leave the two one-line methods as-is, doing a copy & paste for the second listbox, and splitting out the DragDrop handler into its own method like I did above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM