Flex2.0里面提供的Tree组件在效果上和事件处理上都非常的出色。可是在我刚刚尝试去展开和折叠它的时候,却发现这并非易事。在官方文档上看到了有这样一个方法expandChildrenOf(item:Object,open:Boolean),心想应该是使用这个函数了,但是首先就把我给愣住了,我去哪找这个item呢?在ASP.NET2.0里面可是提供了非常好的解决方法的,但是我在这里却死活也想不到这个item是什么,唯一可用的似乎是selectedItem,但是这个不能遍历该Tree所有的顶Node,这个肯定不行。那么这里的item到底是什么呢?其Tree的node又是怎么形成的呢?这个问题在官方文档上无法得到解答,于是只能Google一下了!
查了好久也没有找到适当的方法,最后还是进入了Adobe的
官方网站 ,才找到了一些思路。在上面我看到了这样一行代码:this.Tree.dataProvider.addItemAt(0)。dataProvider?赶快进入Development IDE,输入dataProvider.之后,发现智能提示里面居然没有改方法,Faint!但还是硬着头皮输入了,一测试,居然没有出问题,还正常运行,这个让我对dataProvider产生了一定的质疑,要知道它可只是一个Object啊。看来我对C#的严谨已经完全应用到我对ActionScript的认识上了,要知道ActionScript3.0处理转换要更灵活一些。虽然ActionScript3.0现在已经是一门完全面向对象的语言了,但是却还保留着一些Javascript的烙印,自然也保持着Javascript的灵活性。之所以可以这样处理,可以如下理解:
首先tree.dataProvider = object,然后object(String,XMLNode,XMLList,我们常用的是这三种)被转换成XMLListCollection,再然后dataProvider被赋值,
其值类型是XMLListCollection,于是在我们使用addDataItem或着getDataItem的时候没有出错,FlashPlayer为我们自动转换了类型,并且还可以调用XMLListCollection里面的任何公共方法。这样我们可以再来理解Tree的item是怎么一回事,实际Tree里面的node,完全不能像理解HTML上的select和options或ASP.NET里面的DropDownList控件那样来理解,原因是在后两者里面我们实际上是用的是子控件,也就是说里面显示的Items是作为该控件的子控件来显示的,因而可以直接通过索引访问,并能遍历任何一个子控件。但是在Flex 2.0里面,它的node却完全是根据DataProvider来显示的,它是作为控件的本身的数据而不是子控件来显示的。
哈哈,是不是有点晕了,好好理解一下,我们继续。理解了Tree里面的Node是作为本身的数据形式而显示的,那么我们现在来看看expandChildrenOf(item:Object,opean:Boolean)里面的item是不是能有全新的认识了呢?其实这里面的item就是数据被解析后,被邦定到Tree上面的相应的数据。对于dataProvider,如果你提供的是String或XMLNode或XMLList,那么item就应该是XML了,如果提供的是Array的话,那么item就是Array[i]了。好既然这样理解了就可以看看懂下面的代码了。
private function ExpandAll():void
{
for each(var item:XML in this.LocationNavigation.dataProvider)
this.LocationNavigation.expandChildrenOf(item,true);
}
private function CollapseAll():void{
for each(var item:XML in this.LocationNavigation.dataProvider)
this.LocationNavigation.expandChildrenOf(item,false);
}
怎么样?是不是有“惊醒”的感觉?其实很多东西,
只要自己花时间去认真专研一下,就能搞清楚里面的来龙去脉,最终举一反三,一通百通。笔者写这篇文章之前一共花了13个小时从数据库读数据、尝试多种方法生成XML、用CFC的WebService传递数据、解析XML、转变成需要的XML、ExpandAll()。现在能很明白其间所有的问题,时间虽然花掉了,但是从中得到的学到的东西让人感到踏实。等等还有一个问题,如果在数据邦定后我想将Tree展开,怎么调用ExpandAll出错了呢?
哈哈,这个是FlashPlayer里面的一点问题,在FlashPlayer没有重绘之前,有些函数调用的时候,实际的组件并没有重新生成好。其实Flex 2.0里面提供了很好的解决方案的。任何一个Flex组件都有一个callLater(method:Function,args:Array = null)方法的,但是注意了,
一定不要写成这个样子callLater(ExpandAll());这样会出错的,这个就是直接调用方法了,而不是Later之后调用了,应该写成这样,callLater(ExpandAll),这个特性应该是从JavaScript上保留下来的吧。
OK,今天就到这里吧,睡觉去了-:)