Flex中对Tree进行DragAndDrop

    近期开始学Flex,准备做一个用于左右拖拉的例子出来,具体就是将一个树(或者是List)中的结点拖到右边的一个树上去.这种例子网上已经有很多了,而且很多都是可以运行的.

    这里讲的主要是将一个结点拖到一个树干,而不是随便拖过去的例子.即右边有一个二级的树,第一级称之为parent结点,第二级称之为child结点,我们要做的例子就是将左边的tree(或者是list,其实就是一个list,这里用tree来代替)上的结点,拖到右边的parent结点上,而不是child结点上.

    网上的很多教程都有讲怎么将其拖到右边去,却没有将拖到指定的结点上,最终出来的效果就是结点被随便的放到右边,而不是按照一定逻辑地放在指定parent结点下,成为这个parent结点的一个child结点.

    开始进行,将定义两个tree结点,然后设置dataProvider,接下来,按照教程上的设置右边tree的dragEnter,dragOver,dragDrop等自定义函数.分别如下所示:

dragEnter:

private function enter(event:DragEvent):void {				
	//追加可接受的
	DragManager.acceptDragDrop(UIComponent(event.currentTarget));
}

 

dragOver:

event.preventDefault();
var tree:Tree = event.currentTarget as Tree;
var dropIndex:int = tree.calculateDropIndex(event);
tree.selectedIndex = dropIndex;
var node:XML = tree.selectedItem as XML;
				
if(node.@parent == 'true') {
	//设置成这个,可以进行移动操作				DragManager.showFeedback(DragManager.MOVE);
} else {
	//设置成不可操作,不能进行以后的操作			DragManager.showFeedback(DragManager.NONE);
}

 

 这个没说的,其实就是对拖到哪个结点上作判断,如果是parent结点,则返回一个move操作,否则就返回一个none操作.通过查看tree的源代码,当这个showFeedBack为none时,结点将不会添加至右边去,最终会回退到原来的地方去.而move或者copy等就会执行相应的dragDrop事件了.

dragDrop:

private function drop(event:DragEvent):void {
	event.preventDefault();
	var tree:Tree = event.currentTarget as Tree;
	var ds:DragSource = event.dragSource;
	var nodes:Array = ds.dataForFormat("treeItems") as Array;
	var dropIndex:int = tree.calculateDropIndex(event);
	tree.selectedIndex = dropIndex;
	var selected:XML = tree.selectedItem as XML;

	//右边添加结点
	if(selected.@parent == "true") {
		for each(var i:XML in nodes ) {
		               //删除原来的
			xTree.dataDescriptor.removeChildAt(i.parent(), i,i.childIndex(),xTree.dataProvider);
			//再添加新的
			tree.dataDescriptor.addChildAt(selected, i, 0);
		}
	}
	tree.selectedIndex = -1;
}

     上面代码中tree表示右边的树,xTree表示左边的树.   在Tree中,有个函数必须调用,就是tree.calculateDropIndex,这个函数实际上会执行updateDropData操作,即处理哪个即将要drop到的是哪个item(即哪个结点),感觉很bt的.实际上在dragOver时就可以确定将要拖到哪个结点上去,这里不用简单的用tree.selectedItem来获取右边拖到哪个结点上了,必须用calculateDropIndex来确定信息.

     第二个需要注意的就是从ds中取到的数据实际上是一个array,而不是我原来想的xmlList,如果这里写成as XMLList,则会返回一个null,从而下面处理就会出问题了.

     接下来就准备将数据放到右边去了,而左边的数据则被删掉.值得注意的就是,在现有的tree的源代码中,最终的drop和remove操作,并不是在dragDrop中完成的,而是在dragComplete操作中完成的.就是说,在这里,它不会将数据最终drop下来,而是要等到dragComplete去了.官方的原话如下:

// If not dropping onto ourselves, then add the 
// items here if it's a copy operation.
// If it's a move operation (and not on ourselves), then they 
// are added in dragCompleteHandler and are removed from 
// the source's dragCompleteHandler.  We do both in dragCompleteHandler
// because in order to be re-parented, they must be removed from their
// original source FIRST.  This means our code isn't coupled fantastically 
// as dragCompleteHandler must get the destination tree and 
// cast it to a Tree.

 

    意思就是说,如果是move操作,那么这个操作最终将由源端进行处理,即这个complete操作是由左边的tree来完成的,而不是由右边的tree来完成......这样就有个问题,如果在dragDrop函数中由于某个问题,这个函数执行出错了,dragComplete会照常进行,而将结点移到右边去.

     而且这也造成了,必须在源端上写一个dragComplete函数,我原来想的是在complete函数中将结点从左边移去,结果实现不了,在tree中complete函数中,删除source端结点用了以下三条语句:

parent = getParentItem(items[i]);
index = getChildIndexInParent(parent, items[i]);
removeChildItem(parent, items[i], index);

 其中,第二个函数是private,并且里面同时调用了其他private 属性,想override都不行.就只有在dragDrop下考虑了,所以最终的结果,由上代码所示,在dragDrop中将source结点删除,再往destination端写设置结点.

 

最好还是在source端,加上dragComplte函数,里面将默认的处理禁用掉,如下所示:

private function complete(event:DragEvent):void {
	//让默认的不起作用
	event.preventDefault();
}

 

这样,就达到了将数据从左边移到右边.并且基于这种应用,将demo与服务器端通信连接起来,就可以进行实际应用的开发了:)

 

这是自己在网上参照了很多例子,没有写出左右指定拖动的情况下,乱打乱撞下,成功的代码.在此作一个标记,如果有人碰到与我相同的问题,也可以找到答案了:)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值