WPF/E Drag and Drop: Coco's Dress Up Kit

Drag and drop is a very useful feature of interactive content. You can easily add drag and drop to your WPF/E control by implementing simple event handlers on mouse events. This posting illustrates the use of drag and drop functionality in a creative WPF/E application.

The Zip file ( CocoDressUpKit.zip ) contains all the files used for this application. You can also view the WPF/E application at:

https://wpfesdk.members.winisp.net/samples/coco

Using Drag and Drop in a WPF/E Control
The Coco's Dress Up Kit application allows you to drag and drop decorative objects from a panel onto an image:

click to run sample
Coco's Dress Up Kit

Each decorative object that is on the panel is defined as a Canvas object, and provides event handlers for the mouse events: MouseLeftButtonDown, MouseLeftButtonUp, and MouseMove. Here is the XAML content definition for one of the purple ribbons:

<

Canvas x:Name="Ribbon_01"
MouseLeftButtonDown="javascript:onMouseDown"
MouseLeftButtonUp="javascript:onMouseUp"
MouseMove="javascript:onMouseMove"
Canvas.Top="440" Canvas.Left="140">
<Canvas.RenderTransform>
<RotateTransform Angle="135" />
</Canvas.RenderTransform>
<Polygon Points="0,0 100,30 100,0 0,30"
Fill="#c71585"/>
<Ellipse Canvas.Left="35" Canvas.Top="5"
Height="20" Width="30"
Fill="#cf1f8f"/>
</Canvas>

All decorative objects share the same three mouse event handlers, since the drag and drop functionality is implemented the same for all the objects.

  Note: The Canvas object is used to group all the elements that make up a decorative object. This allows the whole group to act as a unit during drag and drop operations. Likewise, any RenderTransform applied to the Canvas object affects all the elements of the object.

Event Handlers for Drag and Drop Operations
A drag and drop operation is a sequence of three steps:

  • Mouse Down—the object is selected. The object must ensure it has exclusive access to all mouse events generated by the WPF/E control.
  • Mouse Move—the object moves to a new position, relative to the current position of the mouse.
  • Mouse Up—the object stops responding to mouse events.

Let's look at how each of these steps is implemented in a WPF/E control. The onMouseDown event handler in the eventhandler.js file initiates the drag and drop operation by storing the beginning position of the mouse, setting a flag to indicate the drag and drop operation is in effect, and gaining exclusive access to mouse events by invoking the CaptureMouse method:

// Start drag and drop operation.

function onMouseDown(sender, mouseEventArgs)
{
// Set the beginning position of the mouse.
beginX = mouseEventArgs.x;
beginY = mouseEventArgs.y;

isMouseDown = true;
updateStatus(sender.name);

// Ensure object receives all mouse events.
sender.captureMouse();
}

The onMouseMove event handler in the eventhandler.js file determines whether the drag and drop operation is in effect by testing the value of the isMouseDown variable. If the drag and drop operation is in effect, the incremental difference between the last stored mouse position and the current mouse position is applied to the object's Canvas.Top and Canvas.Left values:

// Reposition object during drag and drop operation.

function onMouseMove(sender, mouseEventArgs)
{
// Determine whether the mouse button is down.
// If so, move the object.
if (isMouseDown == true)
{
// Retrieve the current position of the mouse.
var currX = mouseEventArgs.x;
        var currY = mouseEventArgs.y;

        // Reset the location of the object.
        sender["Canvas.Left"] += currX - beginX;
sender["Canvas.Top"] += currY - beginY;

        // Update the beginning position of the mouse.
        beginX = currX;
beginY = currY;
}
}

The onMouseUp event handler in the eventhandler.js file stops the drag and drop operation by invoking the ReleaseMouseCapture method on the object. This method releases the object's exclusive access to the WPF/E control's mouse events. This means that all objects can now receive mouse events:

// Stop drag and drop operation.

function onMouseUp(sender, mouseEventArgs)
{
isMouseDown = false;
updateStatus("");

// Allow all objects to receive mouse events.
    sender.releaseMouseCapture();
}

How Mouse Capture Enables Drag and Drop
The reason why all the decorative objects can share mouse event handlers is that each object enables mouse capture during the drag and drop operation. The end result is that when you drag an object, such as the sunglasses, no mouse events are sent to other objects. So when the sunglasses is dragged under the flower, the flower does not receive mouse events, even though the mouse cursor is directly over the flower:


   Dragging the sunglasses does not trigger mouse events for the flower

Mouse capture also enables drag and drop operations when you move the mouse quickly. As long as mouse capture is enabled, the mouse cursor does not need to be exactly on the object being dragged. Eventually, the object being dragged will render under the mouse cursor.

Enjoy,
Lorin
WPF/E Developer Content Team

and my dog, Coco

Coco's signature
 

CocoDressUpKit.zip