当你利用list-based控件的built-in支持从一个list-based控件拷贝数据到另外一个list-based控件。你会碰见三种情形可能造成你的数据类型信息丢失。
Ø 当你在两个list-based控件中执行拷贝操作,但是在移动操作中并没有执行拷贝操作。
Ø 你的数据类型不是基本的AS数据类型,比如:Date,Number…
Ø 被拷贝的数据类型不是DispalyObject类,或者它的子类。
举例:你定义了一个如下的类,Car.as:
package
{
// dragdrop/Car.as
[RemoteClass]
public class Car extends Object
{
// Constructor.
public function Car()
{
super();
}
// Class properties.
public var numWheels:int;
public var model:String;
public var make:String;
public function get label():String
{
return make + " " + model;
}
}
}
注意到文件当中的元数据(metadata)标记 [RemoteClass].这个标记是用来注册一个Car数据类型,并且这个类型信息可以在拷贝过程中保留的。如果删除了这个标记,类型信息就会丢失了。然后你就可以在程序中利用这个类了:
xmlns:mx=""
layout="absolute" xmlns="*">
public function changeit():void
{
if (list2.dataProvider != null)
{
msg.text += list2.dataProvider[0]
if(list2.dataProvider[0] is Car)
msg.text += " Is Car\n";
else
msg.text += " Is NOT Car\n";
}
}
]]>
id="list1"
x="10" y="45"
width="160" height="120"
dragEnabled="true"
dragMoveEnabled="true">
model="Camry" make="Toyota" numWheels="4"/>
model="Prius" make="Toyota" numWheels="4"/>
id="list2"
x="200" y="45"
width="160" height="120"
dropEnabled="true"/>
label="Access it as button" click="changeit();"/>
id="msg"
x="10" y="200"
width="400" height="100"/>
Built-in的支持只适合于list-based的控件。但是Flex允许所有组件支持拖放操作。即一些nonlist-based的控件也可以执行拖放操作。这就需要处理拖放事件了。
支持拖放操作的类很多:包括DragManger,DragSource以及DragEvent。具体功能参考development guide. 同样对于draginitiator来说,也有很多drag-and-drop 事件:mouseDown,mouseMove,dragStart,dragComplete,dragEnter等。具体功能参考development guide。当为nonlist-based控件增加拖放操作支持时,必须实现事件处理:dragEnter和dragDrop两个事件。其他事件处理可选。对于list-based控件来说,当你设置了dropEnabled属性为true的时候,flex就自动增加了所有事件的处理。
以下的步骤定义了一个拖放操作:
Ø 一个组件成为一个课可拖放的initiator有两种方式:
ü List-based控件其dragEnabled值为ture.
ü Nonlist-based控件或者list-based控件其dragEnabled值为false的。程序必须检测用户的开始拖放的意图,一般的通过mouseMove或者mouseDown来开始一个拖放操作。接着组件必须创建一个—mx.core.DragSource 类实例包含要移动的数据以及数据格式。组件最后条用mx.manager.DragManager.doDrog()方法来出示一个拖放操作。
Ø 当鼠标仍然处于按下的状态,用户可以围绕应用程序界面移动鼠标,Flex将会在程序中显示一个代理镜像(proxy image)。DragManager.defaultDragImageSkin负责设置代理镜像的默认值。注意:当代理镜像没有在drag target上方时,若释放鼠标,flex将在drag initiator产上一个DragComplete事件,并且由DragManager.getFeedback()方法返回DragManger.NONE.
Ø 假如用户移动drag proxy经过一个flex组件,那么flex将调用dragEnter事件:
ü 对于dropEnabled=ture的list-base控件,flex检查看看组件时候能成为一个drop target.
ü 对于nonlist-based控件或者list-based控件其dropEnabled=false的。组件必须为dropEnter事件定义一个事件处理。这个事件处理能检查DragSource对象来决定是否数据可被接受与否。如果可以接受,事件处理将调用DragMnager.accetpDragDrop()方法。你必须为drag target调用这个方法来接收dragOver,dragEixt,dragDrop事件。
ü 如果drop target不接受,drop target组件的的父链将被检查是否可以任何组件可以接受这个drop data.
ü 如果drop target 或者其父链中的组件接受了drop。Flex将在用户移动proxy 到 drop target时候调用dragOver方法。
Ø 如果用户释放了鼠标执行放的操作。Flex将在drop target调用dragDrop事件.
ü 对于dropEnabled=ture的list-base控件,flex将自动添加drop data到drop target中。
ü 对于nonlist-based控件或者list-based控件其dropEnabled=false的, 在drop target必须定义对dragDrop事件的监听来处理增加drop data到drop target中。
Nonlist-based组件的拖放操作
以下的例子是允许用户通过拖放两种颜色框来改变Canvas的背景颜色。
xmlns:mx=""
backgroundColor="white">
import mx.core.DragSource;
import mx.managers.DragManager;
import mx.events.*;
import mx.containers.Canvas;
// Initializes the drag and drop operation.
private function mouseMoveHandler(event:MouseEvent):void {
// Get the drag initiator component from the event object.
var dragInitiator:Canvas=Canvas(event.currentTarget);
// Get the color of the drag initiator component.
var dragColor:int = dragInitiator.getStyle('backgroundColor');
// Create a DragSource object.
var ds:DragSource = new DragSource();
// Add the data to the object.
ds.addData(dragColor, 'color');
// Call the DragManager doDrag() method to start the drag.
DragManager.doDrag(dragInitiator, ds, event);
}
// Called when the user moves the drag proxy onto the drop target.
private function dragEnterHandler(event:DragEvent):void {
// Accept the drag only if the user is dragging data
// identified by the 'color' format value.
if (event.dragSource.hasFormat('color')) {
// Get the drop target component from the event object.
var dropTarget:Canvas=Canvas(event.currentTarget);
// Accept the drop.
DragManager.acceptDragDrop(dropTarget);
}
}
// Called if the target accepts the dragged object and the user
// releases the mouse button while over the Canvas container.
private function dragDropHandler(event:DragEvent):void {
// Get the data identified by the color format
// from the drag source.
var data:Object = event.dragSource.dataForFormat('color');
// Set the canvas color.
myCanvas.setStyle("backgroundColor", data);
}
]]>
width="30" height="30"
backgroundColor="red"
borderStyle="solid"
mouseMove="mouseMoveHandler(event);"/>
width="30" height="30"
backgroundColor="green"
borderStyle="solid"
mouseMove="mouseMoveHandler(event);"/>
text="Drag a color onto the Canvas container."/>
id="myCanvas"
width="100" height="100"
backgroundColor="#FFFFFF"
borderStyle="solid"
dragEnter="dragEnterHandler(event);"
dragDrop="dragDropHandler(event);"/>
id="b1"
label="Clear Canvas"
click="myCanvas.setStyle('backgroundColor', '0xFFFFFF');"
/>
简单描述鼠标mouseDown的事件处理:
1. 创建一个DragSource对象来初始化被拖放的数据以及类型。
2. 调用DragManger.doDrag()方法来开始拖放操作。
DragEnter事件处理:通过DataSource对象来判断被拖放的数据是否于drop target要求的类型兼容。
DragDrop事件处理:当释放鼠标的时候触发该事件,并且dragEnter事件已经掉哟个DragManger.acceptDragDrop()来接受drop.你必须定一个事件处理来把drop data添加到drop target中。
----------------------------待续-----------------------