Flex使用ArrayCollection实现动态Tree

[color=darkred]接触Flex4一个多月,系统地了解了Flex4主要技术。近日想做一个Tree控件的Demo,但发现关于Flex4的很多书籍中主要描述的数据展现控件为DataGrid,List,几乎不涉及Tree,查阅Flex4官方API,看到了Tree控件的简单Demo,使用Flex4内置的XML数据结构填充Tree的dataProvider属性。数据源如下:[/color]
<fx:Declarations>
<fx:XMLList id="treeData">
<node label="MailBox">
<node label="Inbox">
<node label="Marketing"/>
<node label="Product Management"/>
<node label="Personal"/>
</node>
<node label="Outbox">
<node label="Professional"/>
<node label="Personal"/>
</node>
<node label="Spam"/>
<node label="Sent"/>
</node>
</fx:XMLList>
</fx:Declarations>

[color=darkred]在Tree中指定dataProvider属性和labelField属性即可展示树。[/color]
<mx:Tree id="myTree" width="50%" height="100%" 
dataProvider="{treeData}"
labelField="@label"
showRoot="true”>
</mx:Tree>

[color=darkred]但是在实际应用中,面对上万甚至上百万条的数据我们不可能使用静态树,更多是使用动态树。从网上查阅了很多,关于动态树的解决方案基本都是基于XML数据源的,即点击节点时调用RemoteService去Java服务端获取XML来展现子节点。这样的问题对于我来说,就是要在后台对数据库获取的数据进行XML格式的封装,前台也要对XML进行操作。方法不当的话,效率会很低下。我们更希望直接使用Java返回的List对象数组进行树的展示。即在前台使用ArrayCollection作为Tree的dataProvider。结合网上的资料,自己使用了如下的实现方案,在此总结一下。[/color]

[size=medium][color=blue]Server端(Java)[/color][/size]
[color=darkred]使用VO来封装数据库的数据,其中需要有一个类型为List的children属性,由于Tree控件不像DataGrid,List控件,它拥有层次结构。[/color]
package com.ls.vo;

import java.util.List;

public class Spec {
private String id;
private String name;
private String type;
private List<Spec> children;

public Spec(){

}
public Spec(String id, String name, String type) {
super();
this.id = id;
this.name = name;
this.type = type;
}

public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public List<Spec> getChildren() {
return children;
}

public void setChildren(List<Spec> children) {
this.children = children;
}
}

[color=darkred]构建一个Spec的Service类实现业务操作。简单起见,将Service和Dao融合在了一起。[/color]

package com.ls.service;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.longshine.indigo.dbutils.DBUtils;
import com.ls.vo.Spec;

public class SpecService {

public List<Spec> getDevMainTypeList() {
List<Spec> list = new ArrayList<Spec>();
String sql = "select distinct asset_main_type_id id,asset_main_type_name name from scgl.t_jx_spec";
ResultSet res = DBUtils.executeQuery(sql, null);
try {
while (res.next()) {
Spec spec = new Spec(res.getString("id"),
res.getString("name"), "devmaintype"); spec.setChildren(new ArrayList<Spec>());
list.add(spec);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}

public List<Spec> getSpecListByDevMainTypeID(String id) {
String sql = "select * from t_jx_spec where asset_main_type_id=?";
List<Spec> list = new ArrayList<Spec>();
ResultSet res = DBUtils.executeQuery(sql, new Object[] { id });
try {
while (res.next()) {
Spec spec = new Spec(res.getString("id"),
res.getString("name"), "spec");
spec.setChildren(new ArrayList<Spec>());
list.add(spec);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
public List<Spec> getPropListBySpecID(String id) {
String sql = "select * from t_jx_prop where spec_id=?";
List<Spec> list = new ArrayList<Spec>();
ResultSet res = DBUtils.executeQuery(sql, new Object[] { id });
try {
while (res.next()) {
Spec spec = new Spec(res.getString("id"),
res.getString("name"), "prop");
list.add(spec);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
}

[color=darkred]然后在remote-config.xml中设置服务,这样Java端的工作就已经完成。[/color]
<destination id="specService">
<properties>
<source>com.ls.service.SpecService</source>
</properties>
</destination>

[color=blue][size=medium]Client端(Flex4)[/size][/color]
[color=darkred]首先在Flex中构建一个与Java端Spec对象相映射的VO类——SpecVO。[/color]
package vo
{
import mx.collections.ArrayCollection;

[RemoteClass(alias="com.ls.vo.Spec")]
public class SpecVO
{
public var id:String;
public var name:String;
public var type:String;
public var children:ArrayCollection;
public function SpecVO()
{
}
}
}

[color=darkred]接下来就是MXML文件,[/color]
<?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"
minWidth="955" minHeight="600" creationComplete="initApp()">
<fx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.events.ListEvent;
import mx.events.TreeEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import vo.SpecVO;

[Bindable]
[ArrayElementType("vo.SpecVO")]
private var treeData:ArrayCollection=new ArrayCollection();
[Bindable]
private var selectedNode:SpecVO;

protected function initApp():void{
remoteService.getDevMainTypeList();
}

protected function remoteService_faultHandler(event:FaultEvent):void
{
Alert.show(event.fault.message);
}

protected function getDevMainTypeList_resultHandler(event:ResultEvent):void
{
treeData=event.result as ArrayCollection;

}

protected function getSpecListByDevMainTypeID_resultHandler(event:ResultEvent):void
{
selectedNode.children=event.result as ArrayCollection;
treeData.itemUpdated(selectedNode);
}

protected function getPropListBySpecID_resultHandler(event:ResultEvent):void
{
selectedNode.children=event.result as ArrayCollection;
treeData.itemUpdated(selectedNode);
}

protected function specTree_itemOpeningHandler(event:TreeEvent):void
{
selectedNode=event.item as SpecVO;
if(!specTree.isItemOpen(event.item)&&selectedNode.children.length==0)
{
if(selectedNode.type=="devmaintype")
remoteService.getSpecListByDevMainTypeID(selectedNode.id);

else if(selectedNode.type=='spec')
remoteService.getPropListBySpecID(selectedNode.id);
}
}
]]>
</fx:Script>
<fx:Declarations>
<!-- 将非可视元素(例如服务、值对象)放在此处 -->
<s:RemoteObject id="remoteService" destination="specService"
fault="remoteService_faultHandler(event)">
<s:method name="getDevMainTypeList" result="getDevMainTypeList_resultHandler(event)"/>
<s:method name="getSpecListByDevMainTypeID"
result="getSpecListByDevMainTypeID_resultHandler(event)"/>
<s:method name="getPropListBySpecID" result="getPropListBySpecID_resultHandler(event)"/>
</s:RemoteObject>
</fx:Declarations>
<s:Panel width="75%" height="75%" horizontalCenter="0" title="Halo Tree Control Example"
verticalCenter="0">
<s:VGroup left="10" right="10" top="10" bottom="10">
<s:Label width="100%" color="blue" text="Select a node in the Tree control."/>

<mx:HDividedBox width="100%" height="100%">
<mx:Tree id="specTree" width="50%" height="100%" dataProvider="{treeData}"
itemOpening="specTree_itemOpeningHandler(event)" labelField="name"
showRoot="true">
</mx:Tree>
<s:TextArea width="50%" height="100%" text="Selected Item:"/>
</mx:HDividedBox>
</s:VGroup>
</s:Panel>
</s:Application>

[color=darkred]程序初始化时调用RemoteService来加载第一级节点,点击节点时会首先判断节点是否第一次展开,如果是则根据SpecVO的type字段来选择方法去后台获取子节点。resultHandler中将获取的ArrayCollection赋值给节点的children字段,然后使用ArrayCollection的itemUpdate()方法更新数据源。此方法若没有则Tree无法马上渲染子节点。
启动Tomcat,运行Flex页面测试如下:[/color]

[img]http://dl.iteye.com/upload/attachment/603695/be8fa136-3284-3032-8b86-7048a50074b2.png[/img]

[color=darkred]到此基本实现了Flex的Tree的延迟动态加载,至于之后的增删改就容易多了。希望通过后期的了解和学习能有更合适的解决方案。[/color]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值