One of the great features in Flex is the ability to enable drag and drop from data grids with one simple statement, dragEnabled="true". Flick the switch and away you go dragging rows here and there. But what happens when you do not want to see the entire row being dragged around. What if you want to display something more meaniful and less bulky than the entire visible row. Well if you are using the mx.controls.DataGrid you are stuck, however there is a solution. Extend the DataGrid. Here is a working sample, once it is loaded do a right click to view the source code.
By default the DataGrid’s dragImage property is protected and set to ‘mx.controls.dataGridClasses.DataGridDragProxy’. To enable setting a custom dragImage on the DataGrid you can simply extend it to allow the use of a use defined drag image class.
<mx:DataGrid xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridDragProxy;
import mx.core.IUIComponent;
/**
* @public
* class to use as DragProxy image
* set the default value to the standard DataGridDragProxy class
*/
[Bindable]
public var dragProxyImage: Class = DataGridDragProxy;
override protected function get dragImage():IUIComponent
{
var image:IUIComponent = new dragProxyImage();
image.owner = this;
return image;
}
]]>
</mx:Script>
</mx:DataGrid>
Now that the DataGrid has been extended to allow a custom drag image, let’s see how to use it. The first thing to do is to create a class to use as the drag image. It’s a good idea to look over the source code for the mx.controls.dataGridClasses.DataGridDragProxy class as you will be able to see how to create a DragProxy that can work with one or multiple selected rows. Next, drop the new DataGrid into your mxml file, set the dragProxyImage value and you are done.
<controls:DataGrid
dataProvider="{dataSource}"
rowHeight="40"
dragEnabled="true"
height="140"
dragProxyImage="com.dgrigg.controls.CustomDragProxy"
allowMultipleSelection="true">
<controls:columns>
<mx:DataGridColumn headerText="Image" dataField="image">
<mx:itemRenderer>
<mx:Component>
<mx:Image source="{data.image}"/>
</mx:Component>
</mx:itemRenderer>
</mx:DataGridColumn>
<mx:DataGridColumn headerText="Product" dataField="name"/>
<mx:DataGridColumn headerText="Description" dataField="description"/>
</controls:columns>
</controls:DataGrid>
This same solution will work with the mx.controls.List. Click here to view a working sample. Once it is loaded do a right click to view the source code.
I tried this method but had lots of trouble controling where the drag image was drawing itself. I wanted it directly under the mouse, but depending how you select your items and finally start the dragging, it wasn’t always there. I’m guessing it might be because my data grid is wrapped in a canvas buried within many other levels of components.
I ended up just following the examples in the docs for adding drag and drop manually (not using dropEnabled/dragEnabled) in which you can specify a custom drag image class to use. This ended up working out much better for my needs.
Jason
Hi Jason, I would recommend you read over the code in the ‘mx.controls.dataGridClasses.DataGridDragProxy’ class. You will find in there a more robust method for handling the proxy’s x/y coordinates, relative to the row’s position in the datagrid. My example was just a very simplistic one. I have other working versions that use the method in the DataGridDragProxy class and others that use the mouseX and mouseY properties with a localToGlobal call to position the proxy at the mouse pointer, and they work perfectly. It all depends on what you need, but there are a few very easy ways to get the proxy positioned where you need it. If you are trying to do multiple selected rows with the manual DragManager you will quickly discover a pile of problems, which is why I would recommend using the method I have come up with.
Actually, I just ran across some issues with my method today. By using the moveMouse event of the datagrid to initiate the DragManager, it triggers when I move the scroll bars or any time I move the mouse over the datagrid with my mouse button down. This will confuse the users, so I wil look into your method again. I did try messing with localToGlobal to try getting the positioning the way I wanted it, but nothing I tried seemed to worked. I got the x position to follow the mouse propery, bt the y wasn’t consistant depending on how I was selecting multiple rows and which I finally initiating the drag action with. I’ll try again though… thanks for the feedback.
Can you point me to mouseover with ajax in datagrid sample code?
Specifically, image to flv, mov, asx etc…
Thanks,
David Larew
Amazing work Derrick!
Just one question, is there any way to get the DragImageProxy to port over to an embedded Image as a class?
When i drag the dg row, i just want to show one icon, represnting the column, its an embeded png as a class, and i cant get it to work for the life of me..
Thanks!
Hi,
I am able to drag image/component from the DataGrid column, but I want to drag the component from first column and drop it into the second column. My component is a rectangular canvas and I want to drag and drop it into the second column where it should align itself based on the space and the second column canvas should accept the color of the of the canvas being dragged from first column.
Any kind of suggestions?
Thanks in advance,
C. M
Thanks man!
For such nice and quick solution to my problem.
Sorry!
Got new unexpected problems when using this method.
I move the mouse over the datagrid with my mouse button down. This will confuse the users, so I wil look into your method again. I did try messing with localToGlobal to try getting the positioning the way I wanted it, but nothing I tried seemed to worked.
Sorry. Don’t know how to use the above sample. Can you help me?
(1) I am using Flex 3. Does it work also on Flex 3?
(2) Where to place the first part of the sample (in the mxml-file?)
Hi Alois,
You need to take the first sample and use it to create a new class. It extends the datagrid class and provides the functionality to switch the drag proxy. Next, create your own drag proxy based on the standard flex one. Take a look at the source of the sample. Look specifically at the ‘CustomDragProxy’ class. Finally, create an instance of your newly extended DataGrid class and set the reference to the new drag proxy.
Derrick
I just wanted to know how to zoom the image when it is inside the mx:DatagridColumn. When i tried using mx:Zoom it is zooming with in that row, due to that i am seeing scroll bars.
But i wanted to see the image outside the datagrid column on mouse over.
Let me know if any body tried the above scenario.
Hi, I’m trying to do something similar. I have a list with images and I need to drag it to a specific row of the datagrid. Any idea how can I achieve this?
This works great, except I can’t get the positioning correct, it’s always appearing at 0,0 even when explicitly set. I’ve also tried using the method of position in mx.controls.dataGridClasses.DataGridDragProxy to no avail.
Please help!
I tried to use this method in Adobe AIR, but it does not work. Does anybody know how to fix it for Adobe AIR?
Great example! Very clear and simple! It’s just what I need!
Thank you very much!!!