tags:

views:

2626

answers:

2

Flex has built in drag-n-drop for list controls, and allows you to override this. But they don't cover this in examples. The built-in functionality automatically drags the list-item, if you want to override this you find the handlers are being set up on the list itself. What I specifically want to do, is my TileList shows small thumbnails of items I can drag onto a large Canvas. As I drag an item from the list, the drag proxy should be a different image.

So, I followed the technique suggested and it only works if I explicitly set the width/height on the proxy Image. Why?

+2  A: 

It's not obvious until you've tried it =) I struggled with the same thing just a few weeks ago. This was my solution:

The list:

<List>
  <mouseDown>onListMouseDown(event)</mouseDown>
</Tree>

The mouse down handler:

private function onMouseDown( event : MouseEvent ) : void {
  var list : List = List(event.currentTarget);

  // the data of the clicked row, change the name of the class to your own
  var item : MyDataType = MyDataType(list.selectedItem);

  var source : DragSource = new DragSource();

  // MyAwsomeDragFormat is the key that you will retrieve the data by in the
  // component that handles the drop
  source.addData(item, "MyAwsomeDragFormat");

  // this is the component that will be shown as the drag proxy image
  var dragView : UIComponent = new Image();

  // set the source of the image to a bigger version here
  dragView.source = getABiggerImage(item);

  // get hold of the renderer of the clicked row, to use as the drag initiator
  var rowRenderer : UIComponent = UIComponent(list.indexToItemRenderer(list.selectedIndex));

  DragManager.doDrag(
    rowRenderer,
    source,
    event,
    dragView
  );
}

That will start the drag when the user clicks an item in the list. Notice that I don't set dragEnabled and the other drag-related properties on the list since I handle all that myself.

It can be useful to add this to the beginning of the event handler:

if ( event.target is ScrollThumb || event.target is Button ) {
  return;
}

Just to short circuit if the user clicks somewhere in the scrollbar. It's not very elegant but it does the job.

Theo
A: 

I found a simpler answer here. That example extends a DataGrid control, but you can do the same with a List control. In my case, I use an image source instead of Class:

public class CustomDragList extends List {

    [Bindable]
    public var dragProxyImageSource:Object;

    override protected function get dragImage():IUIComponent {
        var image:Image = new Image();
        image.width = 50;
        image.height = 50;
        image.source = dragProxyImageSource;
        image.owner = this;
        return image;
    }
}

Then use that custom list like this:

<control:CustomDragList
    allowMultipleSelection="true"
    dragEnabled="true" 
    dragProxyImageSource="{someImageSource}"
    dragStart="onDragStart(event)"/>

Where 'someImageSource' can be anything you'd normally use for an image source (embedded, linked, etc.)

Ola