by Adobe

adobe_logo_bio

Created

22 March 2010

 Requirements
 
User level
Required products
All Flex (Download trial)
Visual development environments typically let you manipulate objects in an application by selecting them with a mouse and moving them around the screen. The Adobe Flex Drag and Drop Manager lets you select an object, such as an item in a List control, or a Flex control, such as an Image control, and then drag it over another component to add it to that component. All Flex components support the drag-and-drop operation. Flex also includes additional support for the drag-and-drop operation for certain controls, such as the Spark List control and the MX List, Tree, and DataGrid controls.
 
The drag-and-drop operation has three main stages: initiation, dragging, and dropping.
 
  • Initiation: A user initiates a drag-and-drop operation by using the mouse to select a Flex component or an item in a Flex component, and then moving the component or item while holding down the mouse button. For example, a user selects an item in a Spark List control with the mouse and, while holding down the mouse button, moves the mouse several pixels. The selected component is called the drag initiator.
  • Dragging: While holding down the mouse button, the user moves the mouse around the Flex application. Flex displays an image during the drag, which is the drag proxy. The drag source (a DragSource object) contains the data being dragged.
  • Dropping: When a user moves the drag proxy over another Flex component, that component becomes a possible drop target. The drop target can inspect the drag source to determine whether the data is in a format that the target accepts and, if so, let the user drop the data onto it. If the drop target determines that the data is not in an acceptable format, the drop target can disallow the drop operation.
Upon a successful drop operation, Flex adds the data to the target and, optionally, deletes it from its original location.
 
This Quick Start describes the following ways of implementing the drag-and-drop operation in your Flex applications:
 

 
Using drag-and-drop with a Spark List controls

Several Flex controls include built-in support for the drag-and-drop operation. These include the Spark List controls and the MX DataGrid, HorizontalList, List, Menu, PrintDataGrid, TileList, and Tree controls.
 
You can make these controls drag initiators by setting the dragEnabled property to true. Similarly, you can make these controls drop targets by setting the dropEnabled property to true. Flex lets you move items by dragging them from a drag-enabled control to a drop-enabled control, or copy them by dragging while pressing the Control key.
 
 
Copying items by using the drag-and-drop operation
The following example lets you copy items from one Spark List control to another by dragging them. You can copy the same item multiple times from the drag initiator to the drop target.
 
 
Example
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="365" height="225" creationComplete="creationCompleteHandler();"> <fx:Script> <![CDATA[ import mx.collections.ArrayList; private function creationCompleteHandler():void { srclist.dataProvider = new ArrayList(['Reading', 'Skating', 'Movies']); destlist.dataProvider = new ArrayList([]); } ]]> </fx:Script> <s:Panel title="Select activities"> <s:layout> <s:HorizontalLayout paddingTop="5" paddingBottom="5" paddingLeft="5" paddingRight="5"/> </s:layout> <s:VGroup width="50%"> <s:Label text="Available activities"/> <!-- Drag initiator --> <s:List id="srclist" width="100%" height="100" allowMultipleSelection="true" dragEnabled="true"/> </s:VGroup> <s:VGroup width="50%"> <s:Label text="Activities I enjoy"/> <!-- Drop target --> <s:List id="destlist" width="100%" height="100" dropEnabled="true"/> </s:VGroup> </s:Panel> </s:Application>
 
Moving items by using the drag-and drop operation
The default value of the dragMoveEnabled property is false, which only lets you copy items from one control to the other. If you modify the previous example and add the dragMoveEnabled property set to true in the source Spark List control, you can move and copy elements, as the following example shows.
 
The default action is to move the item. To copy an item, hold down the Control key during the drop operation.
 
 
Example
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="365" height="225" creationComplete="creationCompleteHandler();"> <fx:Script> <![CDATA[ import mx.collections.ArrayList; private function creationCompleteHandler():void { srclist.dataProvider = new ArrayList(['Reading', 'Skating', 'Movies']); destlist.dataProvider = new ArrayList([]); } ]]> </fx:Script> <s:Panel title="Select activities"> <s:layout> <s:HorizontalLayout paddingTop="5" paddingBottom="5" paddingLeft="5" paddingRight="5"/> </s:layout> <s:VGroup width="50%"> <s:Label text="Available activities"/> <!-- Drag initiator --> <s:List id="srclist" width="100%" height="100" allowMultipleSelection="true" dragEnabled="true" dragMoveEnabled="true"/> </s:VGroup> <s:VGroup width="50%"> <s:Label text="Activities I enjoy"/> <!-- Drop target --> <s:List id="destlist" width="100%" height="100" dropEnabled="true"/> </s:VGroup> </s:Panel> </s:Application>
 
Two-way drag-and drop support
You can allow two-way dragging and dropping by setting the dragEnabled property and the dropEnabled property to true on both Spark List controls, as follows:
 
 
Example
<?xml version="1.0" encoding="utf-8"?> <!-- DragAndDropSimpleTwoWay.mxml --> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="365" height="225" creationComplete="creationCompleteHandler();"> <fx:Script> <![CDATA[ import mx.collections.ArrayList; private function creationCompleteHandler():void { srclist.dataProvider = new ArrayList(['Reading', 'Skating', 'Movies']); destlist.dataProvider = new ArrayList([]); } ]]> </fx:Script> <s:Panel title="Select activities"> <s:layout> <s:HorizontalLayout paddingTop="5" paddingBottom="5" paddingLeft="5" paddingRight="5"/> </s:layout> <s:VGroup width="50%"> <s:Label text="Available activities"/> <!-- Both drag initiator and drop target --> <s:List id="srclist" width="100%" height="100" allowMultipleSelection="true" dragEnabled="true" dropEnabled="true" dragMoveEnabled="true"/> </s:VGroup> <s:VGroup width="50%"> <s:Label text="Activities I enjoy"/> <!-- Both drag initiator and drop target --> <s:List id="destlist" width="100%" height="100" allowMultipleSelection="true" dragEnabled="true" dropEnabled="true" dragMoveEnabled="true"/> </s:VGroup> </s:Panel> </s:Application>

 
Manually adding drag-and-drop support

To support drag-and-drop operations with non-list-based controls, or with containers, you must explicitly add support by using a series of special classes and events. You use the DragManager, DragSource, and DragEvent classes to implement the drag-and-drop operation.
 
Flex applications use events to control drag-and-drop operations.
 
 
Drag initiator events
When you set a control to act as a drag initiator, you can use the mouseDown, mouseMove, and dragComplete events to manage the drag-and-drop operation.
 
 
The mouseDown and mouseMove events
The mouseDown event is dispatched when a user selects a control with the mouse and holds down the mouse button. The mouseMove event is dispatched when the mouse moves.
 
The following example embeds the images of four Euro coins (1 cent, 2 cent, 5 cent, and 10 cent) and displays them using Image controls. In each of the Image controls, you listen for the mouseMove event and define an event handler method called dragIt() to handle this event. In the dragIt() method, you obtain a reference to the coin image that the event originated on by using the currentTarget property of the event object and save this reference in a local variable called dragInitiator.
 
Next, you create a DragSource instance and call its addData() method to store the value argument that was passed to the dragIt() method. You describe the format of the value argument by using the String "value". You use this string later, when creating your drop target, to check whether you should allow an item to be dropped on it.
 
Because you want to display an image of the coin as the user drags it around, you create an Image instance and set its source to the same coin image that the drag initiator has. You save this image in a local variable called dragProxy.
 
Finally, you call the static doDrag() method on the DragManager class and pass it references to the drag initiator, drag source, the event object, and the drag proxy to start the drag operation.
 
You can drag the coins around but you cannot drop them anywhere because you haven't defined a drop target. The following section describes how to define a drop target.
 
 
Example
<?xml version="1.0" encoding="utf-8"?> <!-- DragAndDropDragInitiatorEvents.mxml --> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="500" height="160"> <fx:Script> <![CDATA[ import mx.managers.DragManager; import mx.core.DragSource; // Embed the various Euro coin images. Images originally // from Wikipedia (http://en.wikipedia.org/wiki/Euro_coins) [Embed("assets/1c.png")] [Bindable] public var OneCent:Class; [Embed("assets/2c.png")] [Bindable] public var TwoCents:Class; [Embed("assets/5c.png")] [Bindable] public var FiveCents:Class; [Embed("assets/10c.png")] [Bindable] public var TenCents:Class; private function dragIt(event:MouseEvent, value:uint):void { // Get the drag initiator component from the event object. var dragInitiator:Image = event.currentTarget as Image; // Create a DragSource object. var dragSource:DragSource = new DragSource(); // Add the data to the object. dragSource.addData(value, 'value'); // Create a copy of the coin image to use as a drag proxy. var dragProxy:Image = new Image(); dragProxy.source = event.currentTarget.source; // Call the DragManager doDrag() method to start the drag. // For information on this method, see // the "Initiating the drag" section. DragManager.doDrag(dragInitiator, dragSource, event, dragProxy); } ]]> </fx:Script> <s:BorderContainer> <s:layout> <s:HorizontalLayout paddingTop="5" paddingBottom="5" paddingLeft="5" paddingRight="5"/> </s:layout> <mx:Image id="oneCent" source="{OneCent}" mouseMove="dragIt(event, 1);"/> <mx:Image id="twoCents" source="{TwoCents}" mouseMove="dragIt(event, 2);"/> <mx:Image id="fiveCents" source="{FiveCents}" mouseMove="dragIt(event, 5);"/> <mx:Image id="tenCents" source="{TenCents}" mouseMove="dragIt(event, 10);"/> </s:BorderContainer> </s:Application>
 
Drop target events
The drop target can use various events, the most important of which are the dragEnter, dragDrop, and dragExit events.
 
 
The dragEnter event
The dragEnter event is dispatched when a drag proxy moves over the drop target from outside the drop target. A component must define an event listener for this event to be a drop target. In the listener, you can change the appearance of the drop target to provide visual feedback to the user that the component can accept the drag operation. For example, you can draw a border around the drop target, or give focus to the drop target.
 
 
The dragExit event
The dragExit event is dispatched when the user drags outside the drop target, but does not drop the data onto the target. You can use this event to restore the drop target to its normal appearance if you modified its appearance in response to a dragEnter event or other event.
 
 
The dragDrop event
The dragDrop event is dispatched when the user releases the mouse over the drop target. You can use this event listener to add the drag data to the drop target.
 
In the following example you create a Spark BorderContainer container to act as the drop target and define handlers to listen for the dragEnter, dragExit and dragDrop events. The BorderContainer container has a Label control inside it that you use to display the total of the coins dropped onto the BorderContainer.
 
In the event handler for the dragEnter event, you check that the drag source contains the "value" format. Only objects that contain this format (i.e., coins in this example) may be dropped on the drop target. If it does, you visually indicate to the user that she may drop the item on the BorderContainer by increasing the thickness of the BorderContainer container's border. You also inform the DragManager that the Box container will accept the drag initiator by calling its acceptDragDrop() method.
 
In the event handler for the dragExit event, you restore the visual appearance of the BorderContainer container to indicate that the drag proxy is no longer over it.
 
Finally, in the event handler for the dragDrop event, which gets called after the user has dropped a coin onto the drop target, you increase the value of the totalValue counter by the value of the coin that was dropped on to the BorderContainer and revert the BorderContainer container to indicate that the drop operation is complete.
 
 
Example
<?xml version="1.0" encoding="utf-8"?> <!-- DragAndDropDragDropTargetEvents.mxml --> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" width="525" height="270"> <s:layout> <s:VerticalLayout/> </s:layout> <fx:Script> <![CDATA[ import mx.events.DragEvent; import spark.components.BorderContainer; import mx.managers.DragManager; import mx.core.DragSource; // Embed the various Euro coin images. Images originally // from Wikipedia (http://en.wikipedia.org/wiki/Euro_coins) [Embed("assets/1c.png")] [Bindable] public var OneCent:Class; [Embed("assets/2c.png")] [Bindable] public var TwoCents:Class; [Embed("assets/5c.png")] [Bindable] public var FiveCents:Class; [Embed("assets/10c.png")] [Bindable] public var TenCents:Class; [Bindable] private var totalValue:uint; private function dragIt(event:MouseEvent, value:uint):void { // Get the drag initiator component from the event object. var dragInitiator:Image = event.currentTarget as Image; // Create a DragSource object. var dragSource:DragSource = new DragSource(); // Add the data to the object. dragSource.addData(value, 'value'); // Create a copy of the coin image to use as a drag proxy. var dragProxy:Image = new Image(); dragProxy.source = event.currentTarget.source; // Call the DragManager doDrag() method to start the drag. // For information on this method, see // the "Initiating the drag" section. DragManager.doDrag(dragInitiator, dragSource, event, dragProxy); } // Called if the user drags a drag proxy onto the drop target. private function dragEnterHandler(event:DragEvent):void { // Get the drop target component from the event object. var dropTarget:BorderContainer=event.currentTarget as BorderContainer; // Accept the drag only if the user is dragging data // identified by the 'value' format value. if (event.dragSource.hasFormat('value')) { // Make the border of the Box thicker to // visually signal to the user that they can // drop the coin there. dropTarget.setStyle("borderThickness", 5); // Accept the drop. DragManager.acceptDragDrop(dropTarget); } } // Called if the user drags the drag proxy away from the drop target. private function dragExitHandler(event:DragEvent):void { // Get the drop target component from the event object. var dropTarget:BorderContainer=event.currentTarget as BorderContainer; // Set the border of the Box to its default value // to visually indicate that the user is no longer // over the drop target. revertBoxBorder(); } // Called if the target accepts the dragged object and the user // releases the mouse button while over the drop target. private function dragDropHandler(event:DragEvent):void { // Get the data identified by the color format from the drag source. var value:uint = event.dragSource.dataForFormat('value') as uint; // Add the value to the total totalValue += value; // Set the border of the Box to its default value revertBoxBorder(); } // Helper method to revert the Box's border to a 1 pixel outline. private function revertBoxBorder():void { amountDisplay.setStyle("borderThickness", 1); } ]]> </fx:Script> <s:BorderContainer> <s:layout> <s:HorizontalLayout paddingTop="5" paddingBottom="5" paddingLeft="5" paddingRight="5"/> </s:layout> <mx:Image id="oneCent" source="{OneCent}" mouseMove="dragIt(event, 1);"/> <mx:Image id="twoCents" source="{TwoCents}" mouseMove="dragIt(event, 2);"/> <mx:Image id="fiveCents" source="{FiveCents}" mouseMove="dragIt(event, 5);"/> <mx:Image id="tenCents" source="{TenCents}" mouseMove="dragIt(event, 10);"/> </s:BorderContainer> <s:BorderContainer id="amountDisplay" borderStyle="solid" borderColor="#000000" backgroundColor="#FFFFFF" width="100%" height="100" dragEnter="dragEnterHandler(event);" dragExit="dragExitHandler(event);" dragDrop="dragDropHandler(event);"> <s:layout> <s:HorizontalLayout paddingTop="5" paddingBottom="5" paddingLeft="5" paddingRight="5"/> </s:layout> <s:Label text="{totalValue + ' pence'}" fontSize="48"/> </s:BorderContainer> </s:Application>

 
For more information