Main.mxml主程序文件:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" xmlns:component="component.*">
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
public var gridDataProvider:ArrayCollection = new ArrayCollection;
/**
* 获取选中项
*/
public function selectedItemChangeHandler():void
{
var result:Array;
if (treeComboBox.treeSelectedItems.length)
{
result = treeComboBox.treeSelectedItems;
}
else
{
result = [treeComboBox.treeSelectedItem];
}
gridDataProvider.source = result;
}
]]>
</mx:Script>
<mx:XMLList id="dataProvider">
<node label="label-1" value="label-1-value">
<node label="label-1_1" value="label-1-value" />
<node label="label-1_2" value="label-1-value" />
<node label="label-1_3" value="label-1-value" />
</node>
<node label="label-2" value="label-1-value" >
<node label="label-2_1" value="label-1-value" />
<node label="label-2_2" value="label-1-value" />
<node label="label-2_3" value="label-1-value" />
</node>
<node label="label-3" value="label-1-value" />
</mx:XMLList>
<mx:CheckBox x="50" y="20" id="checkBox" label="只选子节点" selected="false" />
<component:TreeComboBox id="treeComboBox"
x="50" y="50"
dataProvider="{dataProvider}"
labelField="@label"
treeHeight="150"
width="200"
isParentSelectable="{!checkBox.selected}"
close="{selectedItemChangeHandler()}"
/>
<mx:Label x="50" y="80" text="选中的项目:" fontWeight="bold" />
<mx:DataGrid x="50" y="100"
dataProvider="{gridDataProvider}" >
<mx:columns>
<mx:DataGridColumn headerText="Label" dataField="@label" />
<mx:DataGridColumn headerText="Value" dataField="@value" />
</mx:columns>
</mx:DataGrid>
</mx:Application>
TreeComboBox.as文件:
package component
{
import mx.controls.ComboBox;
import mx.core.ClassFactory;
import mx.events.DropdownEvent;
import mx.events.ListEvent;
[Event(name="treeChange", type="mx.events.ListEvent")]
public class TreeComboBox extends ComboBox
{
private var _ddFactory:ClassFactory;
/**
* 设置项目渲染器
*/
private function get ddFactory():ClassFactory
{
if (_ddFactory == null)
{
_ddFactory = new ClassFactory();
_ddFactory.generator = TreeComboBoxRenderer;
_ddFactory.properties = {
width:this.width,
height:this._treeHeight,
outerDocument:this
};
}
return _ddFactory;
}
/**
* 下拉树的高度
*/
private var _treeHeight:Number;
public function get treeHeight():Number
{
return _treeHeight;
}
public function set treeHeight(value:Number):void
{
this._treeHeight = value;
ddFactory.properties["height"] = this._treeHeight;
}
/**
* 设定是否可以选择父级结点
*/
private var _isParentSelectable:Boolean = true;
[Inspectable(enumeration="true,false", defaultValue="true")]
public function set isParentSelectable(value:Boolean):void
{
_isParentSelectable = value;
}
public function get isParentSelectable():Boolean
{
return _isParentSelectable;
}
/**
* 选中项
*/
private var _treeSelectedItem:Object;
public function set treeSelectedItem(item:Object):void
{
_treeSelectedItem = item;
if (!_treeSelectedItem)
{
selectedIndex = -1;
text = null;
}
dispatchEvent(new ListEvent("treeChange"));
}
[Bindable(event="treeChange")]
public function get treeSelectedItem():Object
{
return _treeSelectedItem;
}
/**
* 选中项的数组(通过CheckBox选择的项目)
*/
private var _treeSelectedItems:Array = [];
public function set treeSelectedItems(array:Array):void
{
if (array)
{
_treeSelectedItems = array;
dispatchEvent(new ListEvent("treeChange"));
}
}
public function get treeSelectedItems():Array
{
return _treeSelectedItems;
}
public function TreeComboBox()
{
super();
this.dropdownFactory = ddFactory;
this.addEventListener(DropdownEvent.OPEN, onComboOpen);
selectedIndex = -1;
}
/**
* 展开下拉树
*/
private function onComboOpen(event:DropdownEvent):void
{
var tree:TreeComboBoxRenderer = dropdown as TreeComboBoxRenderer;
if (treeSelectedItem)
{
tree.expandParents(treeSelectedItem);
tree.selectNode(treeSelectedItem);
}
else
{
try{
if (dataProvider[0])
{
tree.expandItem(dataProvider.getItemAt(0), true);
}
}catch(e:Error)
{
}
}
}
/**
* private
*/
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if(dropdown && treeSelectedItem && treeSelectedItem[labelField] != null)
{
text = treeSelectedItem[labelField];
}
}
/**
* 是否可选
*/
public function isSelectable(data:Object):Boolean
{
return (_isParentSelectable || (data.children().length() <= 0));
}
/**
* 更新选中项
*/
public function updateLabel(selectedItem:Object):void
{
if (selectedItem)
{
treeSelectedItem = selectedItem;
}
}
}
}
TreeComboBoxRenderer.as文件:
package component
{
import mx.controls.Tree;
import mx.core.ClassFactory;
import mx.events.ListEvent;
/**
*
* @author zhangzhicheng
*
*/
public class TreeComboBoxRenderer extends Tree
{
[Bindable]
public var outerDocument:TreeComboBox;
public function TreeComboBoxRenderer()
{
super();
this.itemRenderer = new ClassFactory(CheckBoxTreeRenderer);
this.addEventListener(ListEvent.CHANGE, onSelectionChanged);
this.setStyle("defaultLeafIcon", null);
this.setStyle("folderClosedIcon", null);
this.setStyle("folderOpenIcon", null);
}
/**
* 选中项目更改
*/
private function onSelectionChanged(event:ListEvent):void
{
outerDocument.updateLabel(event.currentTarget.selectedItem);
}
/**
* 打开父结点
*/
public function expandParents(node:Object):void
{
if (node && !isItemOpen(node))
{
expandItem(node, true);
expandParents(node.parent());
}
}
/**
* 设置选中节点
*/
public function selectNode(node:Object):void
{
selectedItem = node;
var idx:int = getItemIndex(selectedItem);
scrollToIndex(idx);
}
/**
* 是否可以选择
*/
override public function isItemSelectable(data:Object):Boolean
{
return super.isItemSelectable(data) && outerDocument.isSelectable(data);
}
/**
* 更新选中项目的数组
*/
public function updateSelectedItems(data:Object, select:Boolean):void
{
if (select)
{
treeSelectedItems.push(data);
}
else
{
treeSelectedItems.splice(treeSelectedItems.indexOf(data), 1);
}
}
/**
* 选中项目数组
*/
public function get treeSelectedItems():Array
{
return outerDocument.treeSelectedItems;
}
}
}
CheckBoxTreeRenderer.as文件: |
package component
{
import flash.events.MouseEvent;
import mx.controls.CheckBox;
import mx.controls.treeClasses.TreeItemRenderer;
import mx.controls.treeClasses.TreeListData;
/**
*
* @author zhangzhicheng
*
*/
public class CheckBoxTreeRenderer extends TreeItemRenderer
{
private var _checkBox:CheckBox;
public function CheckBoxTreeRenderer()
{
super();
}
/**
* @private
*/
override protected function createChildren():void
{
super.createChildren();
if (!_checkBox)
{
_checkBox = new CheckBox;
}
_checkBox.addEventListener(MouseEvent.MOUSE_DOWN, checkBoxMouseDownHandler);
_checkBox.addEventListener(MouseEvent.CLICK, checkBoxClickHandler);
addChild(_checkBox);
}
/**
* @private
*/
override protected function measure():void
{
super.measure();
if (isNaN(explicitWidth))
{
measuredWidth += _checkBox.width + 4;
measuredHeight = label.getExplicitOrMeasuredHeight();
}
else
{
if (_checkBox.measuredHeight > measuredHeight)
measuredHeight = _checkBox.measuredHeight;
}
}
/**
* @private
*/
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
var treeData:TreeListData = (listData as TreeListData);
var startx:Number = treeData ? treeData.indent : 0;
if (disclosureIcon)
{
disclosureIcon.x = startx;
startx = disclosureIcon.x + disclosureIcon.width;
disclosureIcon.setActualSize(disclosureIcon.measuredWidth,
disclosureIcon.measuredHeight);
disclosureIcon.visible = data ?
treeData.hasChildren :
false;
}
if (icon)
{
icon.x = startx;
startx = icon.x + icon.measuredWidth;
icon.setActualSize(icon.measuredWidth, icon.measuredHeight);
}
if (_checkBox)
{
_checkBox.x = startx + 2;
startx = _checkBox.x + _checkBox.measuredWidth + 2;
_checkBox.setActualSize(_checkBox.measuredWidth, _checkBox.measuredHeight);
_checkBox.selected = (owner as TreeComboBoxRenderer).treeSelectedItems.indexOf(data) != -1;
}
label.x = startx;
label.setActualSize(unscaledWidth - startx, measuredHeight);
var verticalAlign:String = getStyle("verticalAlign");
if (verticalAlign == "top")
{
_checkBox.y = 0;
}
else if (verticalAlign == "bottom")
{
_checkBox.y = unscaledHeight - _checkBox.height;
}
else
{
_checkBox.y = (unscaledHeight - _checkBox.height) / 2;
}
}
/**
* @private
*/
protected function checkBoxClickHandler(event:MouseEvent):void
{
event.stopPropagation();
(owner as TreeComboBoxRenderer).updateSelectedItems(data, _checkBox.selected);
}
/**
* @private
*/
protected function checkBoxMouseDownHandler(event:MouseEvent):void
{
event.stopPropagation();
}
}
}