在做开源供应链管理系统的时候,会用到很多树形的描述,需要用到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来描述自己的结构。
下面文章或许你还感兴趣
Today on history:
- 2008: 物资编码的专家咨询会(0)