ドラッグ&ドロップ操作の一部として、移動とコピーを実装できます。
データを移動する場合、データをドロップターゲットに追加し、ドラッグイニシエータから削除します。ドロップターゲットの dragDrop イベントを使用してデータを追加し、ドラッグイニシエータの dragComplete イベントを使用してデータを削除します。
移動の機能を実装するのに必要な作業の量は、ドロップターゲットおよびドラッグイニシエータがリストコントロールであるか、または非リストコントロールであるかによって異なります。
リスト
ベースの
コントロール
追加の作業は必要ありません。リストコントロールは、あるリストコントロールから他のリストコントロールにデータを移動するのに必要な処理のすべてを処理します。例については、ドラッグ&ドロップの実行を参照してください。
非リストコントロール
ドラッグイニシエータが非リストコントロールの場合は、dragComplete イベントのイベントハンドラを実装して、ドラッグデータをドラッグイニシエータから削除する必要があります。ドロップターゲットが非リストコントロールの場合は、dragDrop イベントのイベントハンドラを実装して、データをドロップターゲットに追加する必要があります。例については、例:非リストコントロールでのデータの移動とコピーを参照してください。
リストコントロールでは、ドラッグデータをドロップターゲットに移動するのではなくコピーする場合を除いて、すべてのドラッグ&ドロップ操作を自動化できます。リストコントロールをドロップターゲットとして使用する場合にデータをコピーするには、ドロップターゲットの dragDrop イベントを明示的に処理する必要があります。
非リストコントロールをドロップターゲットとして使用する場合は、移動またはコピーのいずれを行うかに関わらず、dragDrop イベントのイベントハンドラを常に記述する必要があります。
オブジェクト指向の環境でデータをコピーすることは、一般的なタスクではありません。オブジェクトが他のオブジェクトへのポインタを含んでおり、参照されているオブジェクト自体がさらに他のオブジェクトへのポイントを含んでいることがあります。Flex では、ドラッグ&ドロップ操作の一部としてオブジェクト全体のコピーを定義することはせず、ユーザーがオブジェクトのコピーを実装するようにします。これは、ユーザーが対象のデータ形式や要件について直接知っているからです。
一部の環境では、オブジェクトのバイトコピーの作成を簡単にするクローンメソッドを実装するオブジェクトを利用できることがあります。また、ソースオブジェクトの個々のフィールドをターゲットオブジェクトにコピーする処理を記述することが必要になる場合もあります。
次の例では、ある List コントロールから別の List コントロールにアイテムをコピーします。この例では、ドロップターゲットで dropEnabled プロパティを true に設定していますが、dragDrop イベントのイベントハンドラを記述する必要があります。イベントハンドラは Event.preventDefualt() を呼び出して、デフォルトのイベントハンドラを明示的に実行できなくします。ドロップターゲットの dropEnabled プロパティを true に設定するのは、ドロップターゲット上のその他すべてのイベント(dragEnter、dragOver および dragExit)を Flex で自動的に処理できるようにするためです。
dragMoveEnabled プロパティのデフォルト値は false です。この設定の場合は、ある List コントロールから別の List コントロールへのコピーのみが可能です。ドラッグイニシエータで dragMoveEnabled を true に設定するように例を変更すると、エレメントを移動およびコピーできます。リストエレメントをコピーするには、ドラッグ&ドロップ操作中に Ctrl キーを押したままにします。
<?xml version="1.0"?>
<!-- dragdrop\DandDListToListCopy.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.events.DragEvent;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.collections.IList;
import mx.collections.ArrayCollection;
private function initApp():void {
firstList.dataProvider = new ArrayCollection([
{label:"First", data:"1"},
{label:"Second", data:"2"},
{label:"Third", data:"3"},
{label:"Fourth", data:"4"},
]);
secondList.dataProvider = new ArrayCollection([]);
}
private function dragDropHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("items"))
{
// Explicitly handle the dragDrop event.
event.preventDefault();
// Since you are explicitly handling the dragDrop event,
// call hideDropFeedback(event) to have the drop target
// hide the drop indicator.
// The drop indicator is created
// automatically for the list controls by the built-in
// event handler for the dragOver event.
event.currentTarget.hideDropFeedback(event);
// Get drop target.
var dropTarget:List=List(event.currentTarget);
// Get the dragged item from the drag initiator.
// The List control always writes an Array
// to the dragSource object,
// even if there is only one item being dragged.
var itemsArray:Array =
event.dragSource.dataForFormat("items") as Array;
// Copy the dragged data into a new Object.
var tempItem:Object =
{label: itemsArray[0].label, data: itemsArray[0].data};
// Get the drop location in the destination.
var dropLoc:int = dropTarget.calculateDropIndex(event);
// Add the new object to the drop target.
IList(dropTarget.dataProvider).addItemAt(tempItem, dropLoc);
}
}
]]>
</mx:Script>
<mx:HBox>
<mx:List id="firstList"
dragEnabled="true"/>
<mx:List id="secondList"
dropEnabled="true"
dragDrop="dragDropHandler(event);"/>
</mx:HBox>
</mx:Application>
前の例で実行する SWF ファイルは以下のとおりです。
コピーを実行するために、イベントハンドラは新しいオブジェクトを作成し、ドラッグデータの個々のデータフィールドを新しいオブジェクトにコピーします。その後、新しいオブジェクトをドロップターゲットのデータプロバイダに追加します。
例:非リストコントロールでのデータの移動とコピーのセクションの例とは異なり、dragOver イベントハンドラまたは dragComplete イベントハンドラを記述する必要はありません。Flex はコピーを実行できませんが、ユーザーによるコピーまたは移動を認識し、移動時にはドラッグイニシエータからデータを自動的に削除します。
ドラッグ&ドロップを使用して、異なる種類のコントロール間、または異なるデータフォーマットを使用するコントロール間でデータをコピーできます。この状況を処理するには、ドラッグイニシエータのフォーマットからドロップターゲットで必要なフォーマットにデータを変換する、dragDrop イベントのイベントハンドラを記述します。
次の例では、List コントロールから DataGrid コントロールにデータを移動またはコピーできます。dragDrop イベントのイベントハンドラでは、日付を含む新しいフィールドをドラッグデータに追加します。
<?xml version="1.0"?>
<!-- dragdrop\DandDListToDG.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp();">
<mx:Script>
<![CDATA[
import mx.events.DragEvent;
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.collections.IList;
import mx.collections.ArrayCollection;
private function initApp():void {
srcList.dataProvider = new ArrayCollection([
{label:"First", data:"1"},
{label:"Second", data:"2"},
{label:"Third", data:"3"},
{label:"Fourth", data:"4"},
]);
destDG.dataProvider = new ArrayCollection([]);
}
private function dragDropHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("items"))
{
// Explicitly handle the dragDrop event.
event.preventDefault();
// Since you are explicitly handling the dragDrop event,
// call hideDropFeedback(event) to have the drop target
// hide the drop indicator.
// The drop indicator is created
// automatically for the list controls by the built-in
// event handler for the dragOver event.
event.currentTarget.hideDropFeedback(event);
// Get drop target.
var dropTarget:DataGrid =
DataGrid(event.currentTarget);
var itemsArray:Array =
event.dragSource.dataForFormat('items') as Array;
var tempItem:Object =
{ label: itemsArray[0].label,
data: itemsArray[0].data,
date: new Date()
};
// Get the drop location in the destination.
var dropLoc:int = dropTarget.calculateDropIndex(event);
IList(dropTarget.dataProvider).addItemAt(tempItem, dropLoc);
}
}
]]>
</mx:Script>
<mx:HBox>
<mx:List id="srcList"
dragEnabled="true"
dragMoveEnabled="true"/>
<mx:DataGrid id="destDG"
dropEnabled="true"
dragDrop="dragDropHandler(event);">
<mx:columns>
<mx:DataGridColumn dataField="label"/>
<mx:DataGridColumn dataField="data"/>
<mx:DataGridColumn dataField="date"/>
</mx:columns>
</mx:DataGrid>
</mx:HBox>
</mx:Application>
前の例で実行する SWF ファイルは以下のとおりです。
dragComplete イベントは、ドラッグ操作が完了したとき(ドラッグデータをドロップターゲットにドロップするか、ドロップを実行せずにドラッグ&ドロップ操作を終了したとき)に、ドラッグイニシエータで発生します。ドラッグイニシエータでハンドラを指定して、ドラッグが終了するとき、またはターゲットがドロップを受け付けないときにクリーンアップを行うことができます。
dragComplete イベントハンドラを使用する目的の 1 つは、ドロップターゲットに移動したオブジェクトをドラッグイニシエータから削除することです。コントロールからドラッグされるアイテムは、元のアイテムのコピーであり、アイテムそのものではありません。したがって、アイテムをドロップターゲットにドロップするときに、dragComplete イベントハンドラを使用してアイテムをドラッグイニシエータから削除します。
ドラッグ操作の種類(コピーまたは移動)を調べるには、イベントハンドラに渡されたイベントオブジェクトの action プロパティを使用します。このメソッドでは、dragOver イベントハンドラによって設定されたドラッグフィードバックが返されます。詳細については、例:ドロップターゲットの dragOver イベントおよび dragExit イベントの処理を参照してください。
次の例では、ある Canvas コンテナから別の Canvas コンテナに Image コントロールをドラッグします。ドラッグ&ドロップ操作の一環として、Ctrl キーを押し下げたままにすることで、Image コントロールを移動またはコピーできます。移動を実行する場合、dragComplete イベントハンドラは、元の親コンテナから Image コントロールを削除します。
<?xml version="1.0"?>
<!-- dragdrop\DandDImageCopyMove.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="horizontal">
<mx:Script>
<![CDATA[
import mx.managers.DragManager;
import mx.core.DragSource;
import mx.events.DragEvent;
import flash.events.MouseEvent;
// Embed icon image.
[Embed(source='assets/globe.jpg')]
public var globeImage:Class;
// The mouseMove event handler for the Image control
// functioning as the drag initiator.
private function mouseOverHandler(event:MouseEvent):void
{
var dragInitiator:Image=Image(event.currentTarget);
var ds:DragSource = new DragSource();
ds.addData(dragInitiator, "img");
// The drag manager uses the image as the drag proxy
// and sets the alpha to 1.0 (opaque),
// so it appears to be dragged across the canvas.
var imageProxy:Image = new Image();
imageProxy.source = globeImage;
imageProxy.height=10;
imageProxy.width=10;
DragManager.doDrag(dragInitiator, ds, event,
imageProxy, -15, -15, 1.00);
}
// The dragEnter event handler for the Canvas container
// functioning as the drop target.
private function dragEnterHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("img"))
DragManager.acceptDragDrop(Canvas(event.currentTarget));
}
// The dragOver event handler for the Canvas container
// sets the type of drag-and-drop
// operation as either copy or move.
// This information is then used in the
// dragComplete event handler for the source Canvas container.
private function dragOverHandler(event:DragEvent):void
{
if (event.dragSource.hasFormat("img")) {
if (event.ctrlKey) {
DragManager.showFeedback(DragManager.COPY);
return;
}
else {
DragManager.showFeedback(DragManager.MOVE);
return;
}
}
DragManager.showFeedback(DragManager.NONE);
}
// The dragDrop event handler for the Canvas container
// sets the Image control's position by
// "dropping" it in its new location.
private function dragDropHandler(event:DragEvent):void {
if (event.dragSource.hasFormat("img")) {
var draggedImage:Image =
event.dragSource.dataForFormat('img') as Image;
var dropCanvas:Canvas = event.currentTarget as Canvas;
// Since this is a copy, create a new object to
// add to the drop target.
var newImage:Image=new Image();
newImage.source = draggedImage.source;
newImage.x = dropCanvas.mouseX;
newImage.y = dropCanvas.mouseY;
dropCanvas.addChild(newImage);
}
}
// The dragComplete event handler for the source Canvas container
// determines if this was a copy or move.
// If a move, remove the dragged image from the Canvas.
private function dragCompleteHandler(event:DragEvent):void {
var draggedImage:Image =
event.dragInitiator as Image;
var dragInitCanvas:Canvas =
event.dragInitiator.parent as Canvas;
if (event.action == DragManager.MOVE)
dragInitCanvas.removeChild(draggedImage);
}
]]>
</mx:Script>
<!-- Canvas holding the Image control that is the drag initiator. -->
<mx:Canvas
width="250" height="500"
borderStyle="solid"
backgroundColor="#DDDDDD">
<!-- The Image control is the drag initiator and the drag proxy. -->
<mx:Image id="myimg"
source="@Embed(source='assets/globe.jpg')"
mouseMove="mouseOverHandler(event);"
dragComplete="dragCompleteHandler(event);"/>
</mx:Canvas>
<!-- This Canvas is the drop target. -->
<mx:Canvas
width="250" height="500"
borderStyle="solid"
backgroundColor="#DDDDDD"
dragEnter="dragEnterHandler(event);"
dragOver="dragOverHandler(event);"
dragDrop="dragDropHandler(event);">
</mx:Canvas>
</mx:Application>
前の例で実行する SWF ファイルは以下のとおりです。
このページに新しいコメントが追加された場合に、電子メールでの通知を希望する。 | コメントレポート