首先需要知道flex AdvancedDataGrid,DataGrid,List本身是不支持从外部拖进来一个item的(比如我想从一个List中拖进来一行,你会看到鼠标上有个红色的叉叉,表示不允许)。不过要是搞清楚一点AdvancedDataGrid内部工作原理,实现起来也不难(我可是摸索了不少时间啊,:))。
在开始之前,要先明白flex drag drop的工作原理,它的关键之处就是dragEvent,里面包含了各种各样的信息,如,action(drag/drop的类型,COPY,MOVE等),拖动的那个对象,来源对象(就是从哪里拖出来的)。最好去查查文档了解一下,非常推荐官方的devguide_flex3.pdf,里面有一章专门讲drag-drop。
进入正题,AdvancedDataGrid是如何接受drag-drop呢,关键里面有这么几个protected方法。
它们就是用来处理drag-drop事件的(不止AdvancedDataGrid,还有AdvancedListBase和ListBase,以及它们的子类都可以,具体要翻看源码)。我们要做的就是改造他们 — 继承然后重写。拿drapOverHandler为例,它的源码是:
/** * @private */ override protected function dragOverHandler(event:DragEvent):void { // Drag-and-drop not supported for cells if (isCellSelectionMode()) return; if (!(_rootModel is IHierarchicalData) && event.dragSource.hasFormat("items")) { super.dragOverHandler(event); return; } if (event.isDefaultPrevented()) return; if ((!_rootModel || _rootModel is IHierarchicalData) && event.dragSource.hasFormat("treeDataGridItems")) { DragManager.showFeedback(event.ctrlKey ? DragManager.COPY : DragManager.MOVE); showDropFeedback(event); return; } hideDropFeedback(event); DragManager.showFeedback(DragManager.NONE); }
很简单,它首先要检测event.dragSource.hasFormat(”items”),在我的案例里dragEvent正是包含了items,所以它被告诉要用super.dragOverHandler去处理,然后就被否定了。我们要做的就是绕过这个检测,直接执行后面的代码DragManager.showFeedback。(showFeedback是用来显示UI上的一些东西,比如显示横线表示drop的位置在哪儿等等),怎么做呢,重写dragOverHandler:
protected override function dragOverHandler(event:DragEvent):void { if (event.isDefaultPrevented()) { return; } if(event.dragInitiator == this) { super.dragOverHandler(event); } else if(event.dragSource.hasFormat("items")) { DragManager.showFeedback(event.ctrlKey?DragManager.COPY:DragManager.MOVE); showDropFeedback(event) } else { hideDropFeedback(event); DragManager.showFeedback(DragManager.NONE); } }
这样处理后drag-drop进来就不会看到叉叉了,正常拖入,哇哈哈。下面是我改造的dragEnterHandler:
protected override function dragEnterHandler(event:DragEvent):void { if (event.isDefaultPrevented()) { return; } if(event.dragInitiator == this) { super.dragEnterHandler(event); } else if(event.dragSource.hasFormat("items")) { allowDragSelection = false; DragManager.acceptDragDrop(this); DragManager.showFeedback(event.ctrlKey?DragManager.COPY:DragManager.MOVE); showDropFeedback(event) return; } else { hideDropFeedback(event); DragManager.showFeedback(DragManager.NONE); } }
是不是很简单?你需要结合源码来看。除了它们,还有一个非常关键的drapDropHandler,它是用来处理drop之后的操作,这个改写要复杂许多了,这里暂不公开,以后有空写。