Drag-Drop Event Sequence
Let's review the sequence of events and related steps that occur when data is being dragged from, or dropped onto, a form or control.
To make the form or control the target of a drag-and-drop operation, you start by setting AllowDrop
. Next, handle the DragDrop
event, indicating that the operation is complete. The event arguments include the data being moved and its format. In the handler of this event, the target of the drop decides what to do and how to refresh its own user interface in light of the drop.
During the operation, a few other events occur. They are: DragEnter
when the mouse enters the control's bounds; DragOver
while the mouse is moved within the control's bounds; and DragLeave
when the mouse leaves the control. These events are necessary in a limited number of circumstances, like when you're refreshing the UI to reflect the exact, and continuously changing, position of the mouse.
|DoDragDrop is the method that governs the whole drag operation. The method fires events to the target and the source as needed.|
To start a drag-and-drop operation, begin writing a handler for the control's MouseDown
event. The event occurs whenever the (left) mouse button is pressed within the control's bounds. Pressing the mouse button is the first low-level event in any drag-and-drop operation.
The mouse down alone is not a reliable indicator that a drag-and-drop operation has started. When the mouse down event is fired, first store the coordinates at which the mouse button was pressed. More exactly, create a rectangle of a fixed and system-defined size centered around the point of click. Next, when the MouseMove
event arrives, verify that the current coordinates of the mouse point are outside that rectangle. If so, the user is moving the mouse enough to denote a real drag-and-drop action. The beginning of the drag-and-drop operation is marked with a call to DoDragDrop
. You call this method from within the MouseMove
Next, retrieve the data to drag and pack it in a serializable object. The DoDragDrop
method takes two arguments: the actual data and the allowed effects. You pass actual data through an Object
variable, using any valid .NET class, including custom classes.
The parameter indicating the allowed effects of the operation is any combination of the values defined in the DragDropEffects
enum type. Note that if you're dragging across the boundaries of the application (or between objects in the same application but managed by code in different AppDomains), your data object must fulfill an additional requirement: the data should be serializable or, at least, implement the IDataObject
interface. Note that base classes like String, MetaFile, and Bitmap are considered serializable even if they don't explicitly implement the ISerializable
is used to provide users with some feedback about the possible outcome of the ongoing operation, be it a copy, move, or link of the dragged data. Any call to GiveFeedback
occurs within the initial call to the DoDragDrop
method that any source control does to start a drag-and-drop operation. DoDragDrop
determines the control under the current cursor location and raises the event if the control is a valid drop target.
If there is a change in the keyboard state (e.g., the CTRL key is pressed), the QueryContinueDrag
event is also raised to ask the user whether to continue or conclude the operation. The control's code determines what to do by setting a value in the event argument's data. If the operation must continue, the DragOver
event is raised followed by the GiveFeedback
event. The DragOver
events arrive in a pair so that the user is given the most up-to-date feedback on the mouse's location.
Table 2 summarizes the steps to making a control or a form function as the source and the target of a drag-and-drop operation.
Table 2: These are the operations to perform in order to start and conclude a drag-and-drop operation.
To start dragging
To allow dropping
Handle the MouseDown event and pack the data to drag in a managed object.
Set AllowDrop to True.
Handle QueryContinueDrag to monitor changes in the keyboard and mouse state. This is useful if you're supporting multiple operations (e.g., copy, move, link).
Handle DragOver to dynamically check the data being dragged and determines whether you're going to accept the drop.
Handle GiveFeedback to make the mouse pointer reflect any changes to the allowed effects of the operation.
Handle the DragDrop event to conclude the operation. Extract any dragged data and refresh the user interface.
Call the DoDragDrop method and pass in the data to drag. In doing so, you also define the default set of operations allowed (copy, move, link).
Finalize the operation when the method DoDragDrop returns. The return value indicates the outcome of the operation.
Those are the basics of drag-and-drop operations; now let's review the code needed to support a few common situations.