Flex 4 DragManager.doDrag() with .acceptDragDrop() error

While diving into the Flex 4 spark framework I ran into a problem using

mx.managers.DragManager.doDrag() with
mx.managers.DragManager.acceptDragDrop():

If you just drag, accept on dragDrop and then drop without moving the mouse you’ll get this error:

TypeError: Error #1009:
at mx.managers.dragClasses::DragProxy/mouseUpHandler()
[E:\dev\4…\mx\managers\dragClasses\DragProxy.as:591]

This is, because DragProxy didn’t receive a MouseEvent yet. So what you can do is manually send one. See this little use case and test for yourself:

<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"
 
			applicationComplete="construct()"
			height="100%"
			width="100%">
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			import mx.core.DragSource;
			import mx.core.UIComponent;
			import mx.managers.DragManager;
 
			private function construct() : void
			{
				// Get notified whan a global error occurs
				loaderInfo.uncaughtErrorEvents.addEventListener( UncaughtErrorEvent.UNCAUGHT_ERROR, errorHandler );
			}
 
			private function onButtonMouseDown( event : MouseEvent ) : void
			{
				var button : UIComponent = UIComponent( event.target );
				var dragSource:DragSource = new DragSource();
 
				DragManager.doDrag( button, dragSource, event );
 
				// Accept dragDrop
				if ( acceptDragDropCheckBox.selected )
				{
					DragManager.acceptDragDrop( this );
				}
 
				// Avoid error
				if ( avoidErrorCheckBox.selected )
				{
					button.dispatchEvent( new MouseEvent( MouseEvent.MOUSE_MOVE, true,false, button.mouseX, button.mouseY ) );
				}
			}
 
			protected function errorHandler( e : UncaughtErrorEvent ) : void
			{
				Alert.show("An error has occurred and been caught by the global error handler: " + String( e.error ), "My Global Error Handler");
				e.preventDefault();
			}
		]]>
	</fx:Script>
	<s:Label x="20" y="10" text="If you accept dragDrop you need to avoid the error!"/>
	<s:CheckBox id="acceptDragDropCheckBox" x="20" y="30" label="Accept DragDrop"/>
	<s:CheckBox id="avoidErrorCheckBox" x="20" y="50" label="Avoid error"/>
	<mx:Button id="dragButton" x="20" y="110" mouseDown="onButtonMouseDown(event)" label="Drag me. Or click me for error!"/>  
</s:Application>

UPDATE:

A much better way to avoid this error is listening to a DragEvent.DRAG_ENTER before calling DragManager.acceptDragDrop():

<?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"
 
			dragEnter="dragEnterDataRenderer(event)"
 
			height="100%"
			width="100%">
	<fx:Script>
		<![CDATA[
			import mx.core.DragSource;
			import mx.core.UIComponent;
			import mx.events.DragEvent;
			import mx.managers.DragManager;
 
			private function onButtonMouseDown( event : MouseEvent ) : void
			{
				var button : UIComponent = UIComponent( event.target );
				var dragSource:DragSource = new DragSource();
 
				DragManager.doDrag( button, dragSource, event );
			}
 
			private function dragEnterDataRenderer( event : DragEvent ) : void
			{
				DragManager.acceptDragDrop( this );
			}
		]]>
	</fx:Script>
	<mx:Button id="dragButton" x="20" y="20" mouseDown="onButtonMouseDown(event)" label="Click me. Drag me. No Error."/>  
</s:Application>

Leave a Reply

Your email address will not be published. Required fields are marked *