自定义 Tree Data descriptor

在做开源供应链管理系统的时候,会用到很多树形的描述,需要用到mx.controls.Tree来展现,而数据库表定义时,表内有相关联如下:

SQL代码

create table "materialStock"."dbo"."MaterialType"(
"autoId" _autoId not null,
"parentId" _autoId null,
"unit" _unit(20) null,
"name" _name(20) null,
constraint "XPKMaterialType" primary key ("autoId")
)
go

alter table "materialStock"."dbo"."MaterialType"
add constraint "R_6"
foreign key ("parentId")
references "materialStock"."dbo"."MaterialType"("autoId")
go
create unique index "XPKMaterialType" on "materialStock"."dbo"."MaterialType"("autoId")
go

通过JPA就自动生成如下JAVA代码:
Java代码

package com.csgjs.mm.model.domain;

import …

/**
* AbstractMaterialType entity provides the base persistence definition of the
* MaterialType entity.
*
* @author MyEclipse Persistence Tools
*/
@MappedSuperclass
public abstract class AbstractMaterialType implements java.io.Serializable {

// Fields

private Integer autoId;
private MaterialType materialType;
private String unit;
private String name;
private Set<MaterialType> materialTypes = new HashSet<MaterialType>(0);

// Constructors

…

public void setMaterialType(MaterialType materialType) {
this.materialType = materialType;
}

…

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "materialType")
public Set<MaterialCatalog> getMaterialCatalogs() {
return this.materialCatalogs;
}

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "materialType")
public Set<MaterialType> getMaterialTypes() {
return this.materialTypes;
}

public void setMaterialTypes(Set<MaterialType> materialTypes) {
this.materialTypes = materialTypes;
}

}

再由granite data service自动生成如下AS3类:

ActionScript代码

public class AbstractMaterialTypeBase implements IExternalizable {

private var __initialized:Boolean = true;
private var __detachedState:String = null;

private var _autoId:Number;
private var _materialType:MaterialType;
private var _materialTypes:ListCollectionView;
private var _name:String;
private var _unit:String;

meta function isInitialized(name:String = null):Boolean {
if (!name)
return __initialized;

var property:* = this[name];
return (
(!(property is AbstractMaterialType) || (property as AbstractMaterialType).meta::isInitialized()) &&
(!(property is IPersistentCollection) || (property as IPersistentCollection).isInitialized())
);
}

public function set autoId(value:Number):void {
_autoId = value;
}
public function get autoId():Number {
return _autoId;
}

public function set materialType(value:MaterialType):void {
_materialType = value;
}
public function get materialType():MaterialType {
return _materialType;
}

public function set materialTypes(value:ListCollectionView):void {
_materialTypes = value;
}
public function get materialTypes():ListCollectionView {
return _materialTypes;
}

public function set name(value:String):void {
_name = value;
}
public function get name():String {
return _name;
}

public function set unit(value:String):void {
_unit = value;
}
public function get unit():String {
return _unit;
}

public function readExternal(input:IDataInput):void {
__initialized = input.readObject() as Boolean;
__detachedState = input.readObject() as String;
if (meta::isInitialized()) {
_autoId = function(o:*):Number { return (o is Number ? o as Number : Number.NaN) } (input.readObject());
_materialType = input.readObject() as MaterialType;
_materialTypes = input.readObject() as ListCollectionView;
_name = input.readObject() as String;
_unit = input.readObject() as String;
}
else {
_autoId = function(o:*):Number { return (o is Number ? o as Number : Number.NaN) } (input.readObject());
}
}

public function writeExternal(output:IDataOutput):void {
output.writeObject(__initialized);
output.writeObject(__detachedState);
if (meta::isInitialized()) {
output.writeObject(_autoId);
output.writeObject(_materialType);
output.writeObject(_materialTypes);
output.writeObject(_name);
output.writeObject(_unit);
}
else {
output.writeObject(_autoId);
}
}
}
}

当调用远程服务返回的数据是一个ArrayCollection,包含所有的MaterialType的数据集合。

但是Tree的默认的dataDescriptor是查找children属性,可是MaterialType中没有,只有 materialTypes包含子node.

所以在mx.controls.treeClasses.DefaultDataDescriptor继承新类重载getChildren和 isBranch两个方法。

代码如下:

ActionScript代码

package org.bona.controls
{
import flash.utils.Dictionary;

import mx.collections.ArrayCollection;
import mx.collections.ICollectionView;
import mx.collections.XMLListCollection;
import mx.controls.treeClasses.DefaultDataDescriptor;
import mx.controls.treeClasses.ITreeDataDescriptor;

public class TreeDataDescriptor extends DefaultDataDescriptor implements ITreeDataDescriptor
{
/**
*  Constructor.
*/
public function TreeDataDescriptor(children:String=null)
{
super();
childrenField=children;
//trace(‘TreeDataDescriptor Constructor, ’ + childrenField);
}

/**
*  @private
*/
private var ChildCollectionCache:Dictionary=new Dictionary(true);

[Bindable]
public var childrenField:String=null;

override public function getChildren(node:Object, model:Object=null):ICollectionView
{
//          trace(node);
var childrenCollection:ICollectionView=super.getChildren(node, model);
var children:*;
if (childrenCollection != null)
{
//              trace(’super.getChildren =’, childrenCollection);
return childrenCollection;
}
children=node[childrenField];
//          trace(children);

//then wrap children in ICollectionView if necessary
if (children is ICollectionView)
{
childrenCollection=ICollectionView(children);
}
else if (children is Array)
{
var oldArrayCollection:ArrayCollection=ChildCollectionCache[node];
if (!oldArrayCollection)
{
childrenCollection=new ArrayCollection(children);
ChildCollectionCache[node]=childrenCollection;
}
else
{
childrenCollection=oldArrayCollection;
//ArrayCollection(childrenCollection).mx_internal::dispatchResetEvent=false;
ArrayCollection(childrenCollection).source=children;
}

}
else if (children is XMLList)
{
var oldXMLCollection:XMLListCollection=ChildCollectionCache[node];
if (!oldXMLCollection)
{
// double check since XML as dictionary keys is inconsistent
for (var p:*in ChildCollectionCache)
{
if (p === node)
{
oldXMLCollection=ChildCollectionCache[p];
break;
}
}
}

if (!oldXMLCollection)
{
childrenCollection=new XMLListCollection(children);
ChildCollectionCache[node]=childrenCollection;
}
else
{
childrenCollection=oldXMLCollection;

//We don’t want to send a RESET type of collectionChange event in this case.
//XMLListCollection(childrenCollection).mx_internal::dispatchResetEvent=false;
XMLListCollection(childrenCollection).source=children;
}
}
else
{
var childArray:Array=new Array(children);
if (childArray != null)
{
childrenCollection=new ArrayCollection(childArray);
}
}
return childrenCollection;
}

/**
*  Tests a node for termination.
*  Branches are non-terminating but are not required to have any leaf nodes.
*  If the node is XML, returns <code>true</code> if the node has children
*  or a <code>true isBranch</code> attribute.
*  If the node is an object, returns <code>true</code> if the node has a
*  (possibly empty) <code>children</code> field.
*
*  @param node The node object currently being evaluated.
*  @param model The collection that contains the node; ignored by this class.
*
*  @return <code>true</code> if this node is non-terminating.
*/
override public function isBranch(node:Object, model:Object=null):Boolean
{
var branch:Boolean = super.isBranch(node,model);
if (branch)return branch;
if (node == null)
return false;
if (node is Object)
{
try
{
if (node[childrenField] != undefined)
{
branch=true;
}
}
catch (e:Error)
{
}
}
return branch;
}

}

}

在应用程序模块中如下应用:

MXML代码


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:tdd="org.bona.controls.*" creationComplete="{initData();}" viewSourceURL="srcview/index.html">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var datas:ArrayCollection = new ArrayCollection();
[Bindable]
private var selectedItem:MaterialType;

private function initData():void{
var mt:MaterialType = generateMaterialType(‘level top -1′);
generateMaterialType(‘level 2-1′,mt);
generateMaterialType(‘level 2-2′,mt);
generateMaterialType(‘level 2-3′,mt);
datas.addItem(mt);
mt = generateMaterialType(‘level top -2′);
datas.addItem(mt);
}

private function generateMaterialType(name:String,parent:MaterialType=null):MaterialType{
var mt :MaterialType = new MaterialType();
mt.name = name;
if(parent !=null){
if(parent.materialTypes==null){
parent.materialTypes = new ArrayCollection();
}
parent.materialTypes.addItem(mt);
}
return mt;
}

private function selected(e:Event):void{
selectedItem = Tree(e.target).selectedItem as MaterialType;
}

]]>
</mx:Script>
<mx:HDividedBox width="100%" height="100%">
<mx:Tree dataProvider="{datas}" labelField="name" height="100%" width="100%" change="selected(event);">
<mx:dataDescriptor>
<tdd:TreeDataDescriptor childrenField="materialTypes"/>
</mx:dataDescriptor>
</mx:Tree>
<mx:VBox width="100%" height="100%">
<mx:Label text="selected material type:"/>
<mx:TextArea width="100%" height="100%" text="{selectedItem.name}"/>
</mx:VBox>

</mx:HDividedBox>

</mx:Application>

这样就可以自定义childrenField来描述自己的结构。

查看在线Demo

下面文章或许你还感兴趣

  • FDT3.5正式版已经发布
  • 收藏-Flex Builder 3 on Eclipse 3.5
  • JasperReport与JPA结合设计报表
  • spring和toplink集成显式事务配置
  • GDS POJO Helloworld例子(1)
  • WebORB+Flex3.0基于RemoteObject技术开发实例
  • Enterprise IDE Plugin for Flex Builder Public Free Beta
  • 解决Spring Tool Suite和Maven2找不到JDK的问题
  • Maven2 常用命令
  • 收藏Flexmojos Adding libraries to compilation

Today on history:

  1. 2008:  物资编码的专家咨询会(0)

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>