flex4 spark DataGrid 拖放drag drop实现

本文详细介绍了如何通过修改Flex框架的Datagrid组件,使其支持拖放功能,包括修复数据项在特定操作下丢失的问题,并新增与MX框架中DataGrid组件相似的拖放特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://www.riafan.com/article/flex/spark-datagrid-with-support-for-drag-and-drop.html

上面的网址有源码,是在上面做了dragMove修复,修复了 drop到一个 button时 datagrid的 selecteditem数据会被移除的问题

和 新增 dragsouce 的 items属性 更像mx的DataGrid的drag特性呢

DNDragDataGrid.as


package com.dn.components.datagrid
{


import flash.display.DisplayObject;
import flash.geom.Point;

import mx.collections.ArrayList;
import mx.core.DragSource;
import mx.core.IFactory;
import mx.core.IFlexDisplayObject;
import mx.events.DragEvent;
import mx.managers.DragManager;


import spark.components.DataGrid;
import spark.components.Group;
import spark.components.gridClasses.CellPosition;
import spark.components.gridClasses.GridColumn;
import spark.components.gridClasses.IGridItemRenderer;
import spark.events.GridEvent;
/**
*
* @author Hugo.Wang
* 2012-6-15 17:25:25
*/
public class DNDragDataGrid extends DataGrid
{
public function DNDragDataGrid()
{
super();
addEventListener(GridEvent.GRID_MOUSE_DRAG, startDragDrop);
}

private var dropIndex:int;

private var dropIndicator:DisplayObject;

private var _dragEnabled:Boolean = false;

[Inspectable(defaultValue="false")]

public function get dragEnabled():Boolean
{
return _dragEnabled;
}

public function set dragEnabled(value:Boolean):void
{
if (value == _dragEnabled)
return;
_dragEnabled = value;
if(_dragEnabled)
{
addEventListener(DragEvent.DRAG_COMPLETE, dragCompleteHandler);
}
else
{
removeEventListener(DragEvent.DRAG_COMPLETE, dragCompleteHandler);
}
}

private var _dragMoveEnabled:Boolean = false;

[Inspectable(defaultValue="false")]

public function get dragMoveEnabled():Boolean
{
return _dragMoveEnabled;
}

public function set dragMoveEnabled(value:Boolean):void
{
_dragMoveEnabled = value;
}

private var _dropEnabled:Boolean = false;

[Inspectable(defaultValue="false")]

public function get dropEnabled():Boolean
{
return _dropEnabled;
}

public function set dropEnabled(value:Boolean):void
{
if (value == _dropEnabled)
return;
_dropEnabled = value;
if(_dropEnabled)
addEventListener(DragEvent.DRAG_ENTER, dragEnterHandler);
else
removeEventListener(DragEvent.DRAG_ENTER, dragEnterHandler);
}

private var _draggableColumns:Boolean = false;

[Inspectable(defaultValue="false")]

public function get draggableColumns():Boolean
{
return _draggableColumns;
}

public function set draggableColumns(value:Boolean):void
{
_draggableColumns = value;
}

private function startDragDrop(event:GridEvent):void
{
if (DragManager.isDragging)
return;

if (event.rowIndex == -1 && event.itemRenderer)
// dragging headers
startColumnDragDrop(event);
else
startRowDragDrop(event);
}

private var dragColumn:GridColumn;

protected function startColumnDragDrop(event:GridEvent):void
{
if(!(draggableColumns))
{
return;
}

dragColumn = event.column;
var ds:DragSource = new DragSource();
ds.addData(dragColumn, "spark.components.gridClasses.GridColumn");
var factory:IFactory = dragColumn.headerRenderer;
if (!factory)
factory = columnHeaderGroup.headerRenderer;
var renderer:IGridItemRenderer = IGridItemRenderer(factory.newInstance());
renderer.visible = true;
renderer.column = dragColumn;
renderer.label = dragColumn.headerText;
var currentRenderer:IGridItemRenderer = columnHeaderGroup.getHeaderRendererAt(event.columnIndex);
renderer.width = currentRenderer.width;
renderer.height = currentRenderer.height;
renderer.x = currentRenderer.x;
renderer.y = currentRenderer.y;
renderer.prepare(false);
DragManager.doDrag(this, ds, event, renderer as IFlexDisplayObject);
renderer.owner = this;
columnHeaderGroup.addEventListener(DragEvent.DRAG_ENTER, columnDragEnterHandler)
columnHeaderGroup.addEventListener(DragEvent.DRAG_COMPLETE, columnDragCompleteHandler);
}

protected function columnDragEnterHandler(event:DragEvent):void
{
if (event.dragSource.hasFormat("spark.components.gridClasses.GridColumn"))
{
columnHeaderGroup.addEventListener(DragEvent.DRAG_OVER, columnDragOverHandler);
columnHeaderGroup.addEventListener(DragEvent.DRAG_EXIT, columnDragExitHandler);
columnHeaderGroup.addEventListener(DragEvent.DRAG_DROP, columnDragDropHandler);
showColumnDropFeedback(event);
DragManager.acceptDragDrop(columnHeaderGroup);
}
}

protected function columnDragOverHandler(event:DragEvent):void
{
if (event.dragSource.hasFormat("spark.components.gridClasses.GridColumn"))
{
showColumnDropFeedback(event);
DragManager.acceptDragDrop(columnHeaderGroup);
}
}

protected function columnDragExitHandler(event:DragEvent):void
{
columnHeaderGroup.removeEventListener(DragEvent.DRAG_OVER, columnDragOverHandler);
columnHeaderGroup.removeEventListener(DragEvent.DRAG_EXIT, columnDragExitHandler);
columnHeaderGroup.removeEventListener(DragEvent.DRAG_DROP, columnDragDropHandler);
cleanUpDropIndicator();
}

private function columnDragDropHandler(event:DragEvent):void
{
columnHeaderGroup.removeEventListener(DragEvent.DRAG_OVER, columnDragOverHandler);
columnHeaderGroup.removeEventListener(DragEvent.DRAG_EXIT, columnDragExitHandler);
columnHeaderGroup.removeEventListener(DragEvent.DRAG_DROP, columnDragDropHandler);
dropColumn(event);
}

private function columnDragCompleteHandler(event:DragEvent):void
{
columnHeaderGroup.removeEventListener(DragEvent.DRAG_ENTER, columnDragEnterHandler);
cleanUpDropIndicator();
}


private function dropColumn(event:DragEvent):void
{
if (dropIndex != dragColumn.columnIndex)
{
var oldIndex:int = dragColumn.columnIndex;
columns.removeItemAt(dragColumn.columnIndex);
if (dropIndex > oldIndex)
dropIndex--;
columns.addItemAt(dragColumn, dropIndex);
}
cleanUpDropIndicator();
}


private function showColumnDropFeedback(event:DragEvent):void
{
var pt:Point = new Point(event.stageX, event.stageY);
pt = columnHeaderGroup.globalToLocal(pt);
var newDropIndex:int = columnHeaderGroup.getHeaderIndexAt(pt.x, pt.y);
if (newDropIndex != -1)
{
var renderer:IGridItemRenderer = columnHeaderGroup.getHeaderRendererAt(newDropIndex);
if (!dropIndicator)
{
dropIndicator = new ColumnDropIndicator();
dropIndicator.height = renderer.height;
columnHeaderGroup.overlay.addDisplayObject(dropIndicator);
}
if (pt.x < renderer.x + renderer.width / 2)
dropIndicator.x = renderer.x - dropIndicator.width / 2;
else
{
dropIndicator.x = renderer.x + renderer.width - dropIndicator.width / 2;
newDropIndex++;
}
dropIndex = newDropIndex;
}
else
{
cleanUpDropIndicator();
}
}


protected function copySelectedItems(useDataField:Boolean = true):Array
{
var tmp:Array = [];

var items:Vector.<Object> = selectedItems;
for (var i:int = 0; i < items.length; i++)
{
if(useDataField){
tmp[i]=items[i];
}else{
tmp[i]=selectedIndices[i];
}
}

return tmp;
}
/**
* @private
*/
private function copySelectedItemsForDragDrop():Vector.<Object>
{
// Copy the vector so that we don't modify the original
// since selectedIndices returns a reference.
var draggedIndices:Vector.<int> = selectedIndices.slice(0, selectedIndices.length);
var result:Vector.<Object> = new Vector.<Object>(draggedIndices.length);

// Sort in the order of the data source
draggedIndices.sort(compareValues);

// Copy the items
var count:int = draggedIndices.length;
for (var i:int = 0; i < count; i++)
result[i] = dataProvider.getItemAt(draggedIndices[i]);
return result;
}

protected function startRowDragDrop(event:GridEvent):void
{
if(!dragEnabled)
return;

var newIndex:int = event.rowIndex;

var ds:DragSource = new DragSource();
ds.addHandler(copySelectedItems, "items");
ds.addHandler(copySelectedItemsForDragDrop, "itemsByIndex");

// Calculate the index of the focus item within the vector
// of ordered items returned for the "itemsByIndex" format.
var caretIndex:int = 0;
var draggedIndices:Vector.<int> = selectedIndices;
var count:int = draggedIndices.length;
for (var i:int = 0; i < count; i++)
{
if (newIndex > draggedIndices[i])
caretIndex++;
}
ds.addData(caretIndex, "caretIndex");

var proxy:Group = new Group();
proxy.width = grid.width;
DragManager.doDrag(this, ds, event, proxy as IFlexDisplayObject,
0, -rowHeight, 0.5, dragMoveEnabled);

const visibleColumnIndices:Vector.<int> = grid.getVisibleColumnIndices();
count = visibleColumnIndices.length;
const visibleRowIndices:Vector.<int> = grid.getVisibleRowIndices();
//for scrolled renderers
var rIndex:int = grid.getVisibleRowIndices().indexOf(newIndex);
for (i = 0; i < count; i++)
{
var currentRenderer:IGridItemRenderer = grid.getItemRendererAt(newIndex, visibleColumnIndices[i]);
var factory:IFactory = columns.getItemAt(i).itemRenderer;
if (!factory)
factory = itemRenderer;
var renderer:IGridItemRenderer = IGridItemRenderer(factory.newInstance());
renderer.visible = true;
if(currentRenderer)
{
renderer.column = currentRenderer.column;
renderer.rowIndex = currentRenderer.rowIndex;
renderer.label = currentRenderer.label;
renderer.x = currentRenderer.x;
renderer.y = rIndex * rowHeight;
renderer.width = currentRenderer.width;
renderer.height = currentRenderer.height;
renderer.prepare(false);
proxy.addElement(renderer);
renderer.owner = this;
}
}
proxy.height = renderer.height;

}

protected function dragEnterHandler(event:DragEvent):void
{
if (event.dragSource.hasFormat("itemsByIndex"))
{
grid.addEventListener(DragEvent.DRAG_OVER, rowDragOverHandler);
grid.addEventListener(DragEvent.DRAG_EXIT, rowDragExitHandler);
grid.addEventListener(DragEvent.DRAG_DROP, rowDragDropHandler);
showRowDropFeedback(event);
DragManager.acceptDragDrop(grid);
}
}

protected function rowDragOverHandler(event:DragEvent):void
{
if (event.dragSource.hasFormat("itemsByIndex"))
{
showRowDropFeedback(event);
DragManager.acceptDragDrop(grid);
}
}

protected function rowDragExitHandler(event:DragEvent):void
{
grid.removeEventListener(DragEvent.DRAG_OVER, columnDragOverHandler);
grid.removeEventListener(DragEvent.DRAG_EXIT, columnDragExitHandler);
grid.removeEventListener(DragEvent.DRAG_DROP, columnDragDropHandler);
cleanUpRowDropIndicator();
}

protected function rowDragDropHandler(event:DragEvent):void
{
grid.removeEventListener(DragEvent.DRAG_OVER, columnDragOverHandler);
grid.removeEventListener(DragEvent.DRAG_EXIT, columnDragExitHandler);
grid.removeEventListener(DragEvent.DRAG_DROP, columnDragDropHandler);
dropRow(event);
}

protected function dragCompleteHandler(event:DragEvent):void
{
if (event.isDefaultPrevented())
return;
// Remove the dragged items only if they were drag moved to
// a different list. If the items were drag moved to this
// list, the reordering was already handles in the
// DragEvent.DRAG_DROP listener.
if (!dragMoveEnabled ||
event.action != DragManager.MOVE ||
event.relatedObject == this)
return;

// Clear the selection, but remember which items were moved
var movedIndices:Vector.<int> = selectedIndices;
selectedIndices = new Vector.<int>();
validateProperties();
// Remove the moved items
movedIndices.sort(compareValues);
var count:int = movedIndices.length;
for (var i:int = count - 1; i >= 0; i--)
{
dataProvider.removeItemAt(movedIndices[i]);
}
dropIndex = 0;
}

private function showRowDropFeedback(event:DragEvent):void
{
DragManager.showFeedback(event.ctrlKey ? DragManager.COPY : DragManager.MOVE);
var pt:Point = new Point(event.stageX, event.stageY);
pt = grid.globalToLocal(pt);
var pos:CellPosition = grid.getCellAt(pt.x, pt.y);
var newDropIndex:int = pos ? pos.rowIndex : - 1;
if (newDropIndex != -1)
{
var renderer:IGridItemRenderer = grid.getItemRendererAt(pos.rowIndex, pos.columnIndex);
if (!dropIndicator)
{
dropIndicator = new RowDropIndicator();
dropIndicator.width = width;
grid.overlay.addDisplayObject(dropIndicator);
}
if (pt.y < renderer.y + renderer.height / 2)
dropIndicator.y = renderer.y - dropIndicator.height / 2;
else
{
dropIndicator.y = renderer.y + renderer.height - dropIndicator.height / 2;
newDropIndex++;
}
dropIndex = newDropIndex;
}
else
{
cleanUpRowDropIndicator();
}
}

private function dropRow(event:DragEvent):void
{
if(event.dragSource.hasFormat("itemsByIndex"))
{
var data:Vector.<Object> = event.dragSource.dataForFormat("itemsByIndex") as Vector.<Object>;
var count:int = data.length;
var i:int;

if (event.dragInitiator == this)
{
for (i = 0; i < count; i++)
{
var index:int = dataProvider.getItemIndex(data[i]);
dataProvider.removeItemAt(index);
if (index < dropIndex)
dropIndex--;
}
}

if(dataProvider == null)
{
dataProvider = new ArrayList();
}

for (i = 0; i < count; i++)
{
dataProvider.addItemAt(data[i], dropIndex++);
}
}
cleanUpRowDropIndicator();
}

private function cleanUpDropIndicator():void
{
if (dropIndicator)
{
dropIndex == -1;
if( columnHeaderGroup.overlay.numDisplayObjects > 0)
{
columnHeaderGroup.overlay.removeDisplayObject(dropIndicator);
dropIndicator = null;
}
}
}

private function cleanUpRowDropIndicator():void
{
if (dropIndicator)
{
dropIndex == -1;
if(grid.overlay.numDisplayObjects > 0)
{
grid.overlay.removeDisplayObject(dropIndicator);
dropIndicator = null;
}
}
}

/**
* @private
* Used to sort the selected indices during drag and drop operations.
*/
private function compareValues(a:int, b:int):int
{
return a - b;
}
}
}


RowDropIndicator.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group 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="100%" height="3">
<s:Rect left="1" right="1" top="1" bottom="1">
<s:fill>
<s:SolidColor color="0x2B333C"/>
</s:fill>
</s:Rect>
<s:Rect left="0" right="0" top="0" bottom="0">
<s:stroke>
<s:SolidColorStroke weight="1"/>
</s:stroke>
</s:Rect>
</s:Group>


ColumnDropIndicator.mxml

<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx">
<s:Rect width="1" height="100%" right="1">
<s:fill>
<s:SolidColor color="0x0167FF"/>
</s:fill>
</s:Rect>
</s:Group>


app.mxml

<?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"
xmlns:c="components.*"
width="800" height="600">
<s:layout>
<s:VerticalLayout horizontalAlign="center" paddingTop="30"/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.core.IUIComponent;
import mx.events.DragEvent;
import mx.managers.DragManager;

protected function addItemButton_dragDropHandler(event:DragEvent):void
{
// TODO Auto-generated method stub
try{
var obj:Object=event.dragSource.dataForFormat('items')[0];
Alert.show(obj.birthday);
}catch(er:Error){}
}

protected function button1_dragEnterHandler(event:DragEvent):void
{
// TODO Auto-generated method stub
DragManager.acceptDragDrop(IUIComponent(event.target));
}

]]>
</fx:Script>

<fx:Declarations>
<s:ArrayList id="al">
<s:DataItem birthday="07/23/1987" salary="6000" userName="Jim"/>
<s:DataItem birthday="06/12/1987" salary="5500" userName="Jane"/>
<s:DataItem birthday="12/06/1988" salary="8000" userName="Tom"/>
<s:DataItem birthday="01/12/1988" salary="6000" userName="Kite"/>
<s:DataItem birthday="05/28/1987" salary="7000" userName="Mike"/>
</s:ArrayList>
</fx:Declarations>
<s:Button
label="drop in"
dragEnter="button1_dragEnterHandler(event)"
dragDrop="addItemButton_dragDropHandler(event)"
>

</s:Button>
<mx:DataGrid width="400"
dataProvider="{new ArrayList(al.source.concat())}"
dragEnabled="true" dragDrop="true"
draggableColumns="true" rowCount="5"
allowMultipleSelection="true">
<mx:columns>
<mx:DataGridColumn dataField="userName" headerText="Name"/>
<mx:DataGridColumn dataField="birthday" headerText="Bithday"/>
<mx:DataGridColumn dataField="salary" headerText="Salary"/>
</mx:columns>
</mx:DataGrid>

<c:DataGridEx width="400" dataProvider="{al}" dragEnabled="true" draggableColumns="true"
dragMoveEnabled="true" dropEnabled="true" requestedRowCount="5" selectionMode="multipleRows">
<c:columns>
<s:ArrayList>
<s:GridColumn dataField="userName" headerText="Name"/>
<s:GridColumn dataField="birthday" headerText="Bithday"/>
<s:GridColumn dataField="salary" headerText="Salary"/>
</s:ArrayList>
</c:columns>
</c:DataGridEx>

<c:DataGridEx id="dgex" width="400" dragEnabled="true" dropEnabled="true" requestedRowCount="5">
<c:columns>
<s:ArrayList>
<s:GridColumn dataField="userName" headerText="Name"/>
<s:GridColumn dataField="birthday" headerText="Bithday"/>
<s:GridColumn dataField="salary" headerText="Salary"/>
</s:ArrayList>
</c:columns>
</c:DataGridEx>

<s:List height="90" dragEnabled="true" dropEnabled="true"
labelField="userName"/>
</s:Application>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值