Drag and Drop

Drag and Drop has a drop source and a drop target. Each must be configured to participate in Drag and Drop.

Source

To start the Drag and Drop operation, call the DoDragDrop method in the mouse down handler. Specify what is being dragged and the drag effect that is allowed.

DoDragDrop(this.Text, DragDropEffects.Copy);

Target

Set the AllowDrop property of the control to true.

At a minimum, handle two events: DragEnter and DragDrop.

DragEnter

void DragEnter(object sender, DragEventArgs e)

In the DragEnter handler, test the type of the data that is being dragged. If it an acceptable type, then set the DragDropEffect. The simplest effect to implement is Copy. If the data is not an acceptable type, then set the effect to None. The effect will also control the cursor that appears when dragging. If the effect is set to None, then the X cursor appears.

The effect can be set through the DragEventArgs parameter to the DragEnter handler.

Drag and Drop uses the clipboard to transfer data. The way to test the type of the data in the clipboard is through the DragEventArgs. Test the type of the data through the Data property of the DragEventArgs and its GetDataPresent method.

if ( e.Data.GetDataPresent(typeof(string)) ) {
  e.Effect = DragDropEffects.Copy;
}
else
{
  e.Effect = DragDropEffects.None;
}

DragDrop

void DragDrop(object sender, DragEventArgs e)

This is the handler that does the work of dropping the data. Use the GetData method of the Data property in the DragEventArgs.

textBox1.Text = (String) e.Data.GetData(typeof(String));

Multiple Effects

It is possible to specify multiple drag effects and allow the user to select which one. A typical choice would be between copy and move. These are the same, except that the drop source must delete its data after the copy is complete.

The DragEventArgs has a property that is an integer that indicates which key was pressed: none, control, shift. Create a convenient enumeration to help remember what all the numbers mean.

enum KeyState {
  Left = 1,
  Right = 2,
  Shift = 4,
  Control = 8,
  Middle = 16,
  Alt = 32
}

In order to know if the user changed keys after the drag started, handle the DragOver event. Set the effect based on the current state of the keys.

DragEnter - call SetEffect helper.

DragOver - call SetEffect helper.

void SetEffect(DragEventArgs e) {
  KeyState state = (KeyState) e.KeyState;
  if ( e.Data.GetDataPresent(typeof(String)) ) {
    if( (state & KeyState.Control) == KeyState.Control) {
      e.Effect = DragDropEffects.Copy;
    } else { 
      e.Effect = DragDropEffects.Move;
    }
  } else {
    e.Effect = DragDropEffects.None;
  }
}

The DragDrop handler does not need to be changed, since it will only perform the current operation specified by the user.

More than one effect can be specified in the call to DoDragDrop. The DoDragDrop method returns the effect that was used in the operation. If it is a move operation, then the source will need to delete its copy of the data. If the returned effect is move, then delete the source data.

DragDropEffects action = DoDragDrop(
  this.Text, DragDropEffects.Copy | DragDropEffects.Move);

if (action == DragDropEffects.Move) this.Text = ""; 

Changing the Mouse Pointer

When a drag event is initiated, the GiveFeedback event is fired. During the event, changes to the appearance of the form can be made, like changing the mouse pointer or the backbround color of the source.