在包common.control.tree下创建类TreeCheckBoxRender,其中关键的是tree组建的invalidateList(),实现Tree的自动刷新.在checkbox的事件响应下,递归其子节点就可以修改自己的selected的值(其中data的该checkbox对象的一个抽象,或者说是一个引用),然后分发事件,由tree的invalidateList()实现,级联选择。
package common.control.tree { import flash.events.Event; import flash.events.MouseEvent; import mx.controls.Alert; import mx.controls.CheckBox; import mx.controls.Tree; import mx.controls.treeClasses.TreeItemRenderer; import mx.controls.treeClasses.TreeListData; import mx.events.TreeEvent; /** * 支持CheckBox的TreeItemRenderer * @author Montage * @modify chenzhimin */ public class TreeCheckBoxRender extends TreeItemRenderer { public function TreeCheckBoxRender() { super(); } /** * 表示CheckBox控件从data中所取数据的字段 */ private var _selectedField:String = "selected"; protected var checkBox:CheckBox; /** * 构建CheckBox */ override protected function createChildren():void { super.createChildren(); checkBox = new CheckBox(); addChild( checkBox ); checkBox.addEventListener(Event.CHANGE, changeHandler); checkBox.addEventListener(MouseEvent.CLICK,updateCheck); } protected function updateCheck(e:Event):void{ var b:Boolean=this.dispatchEvent(new Event("updateTreeEvent",true)); } /** * 点击checkbox时,更新dataProvider * @param event */ protected function changeHandler( event:Event =null):void { if( data && data[_selectedField] != undefined ) { data[_selectedField] = checkBox.selected; } if(data.hasOwnProperty("children")){ var arr:Array=data["children"]; for(var i:int;i<arr.length;i++){ var obj:Object=arr[i]; obj[_selectedField]=checkBox.selected; } } } /** * 初始化控件时, 给checkbox赋值 */ override protected function commitProperties():void { super.commitProperties(); // trace(data[_selectedField]) if( data && data[_selectedField] != undefined ) { checkBox.selected = data[_selectedField]; } else { checkBox.selected = false; } } /** * 重置itemRenderer的宽度 */ override protected function measure():void { super.measure(); measuredWidth += checkBox.getExplicitOrMeasuredWidth(); } /** * 重新排列位置, 将label后移 * @param unscaledWidth * @param unscaledHeight */ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { super.updateDisplayList(unscaledWidth, unscaledHeight); var startx:Number = data ? TreeListData( listData ).indent : 0; if (disclosureIcon) { disclosureIcon.x = startx; startx = disclosureIcon.x + disclosureIcon.width; disclosureIcon.setActualSize(disclosureIcon.width, disclosureIcon.height); disclosureIcon.visible = data ? TreeListData( listData ).hasChildren : false; } if (icon) { icon.x = startx; startx = icon.x + icon.measuredWidth; icon.setActualSize(icon.measuredWidth, icon.measuredHeight); } checkBox.move(startx, ( unscaledHeight - checkBox.height ) / 2 ); label.x = startx + checkBox.getExplicitOrMeasuredWidth(); } } }
下面是测试MXML
<?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="application1_creationCompleteHandler(event)"> <fx:Declarations> <!-- Place non-visual elements (e.g., services, value objects) here --> </fx:Declarations> <fx:Script> <!--[CDATA[ import mx.collections.ArrayCollection; import mx.events.FlexEvent; [Bindable] public var collection:ArrayCollection = new ArrayCollection([ { "name" : "上海", "selected":false, "children":[ { "name":"黄浦", "selected":false }, { "name":"浦东", "selected":true }, { "name":"静安", "selected":false }, { "name":"徐汇", "selected":false } ]}, { "name":"北京", "selected":false, "children":[ { "name":"海淀", "selected":false }, { "name":"朝阳", "selected":true }, { "name":"丰台", "selected":false } ]} ]); protected function application1_creationCompleteHandler(event:FlexEvent):void { // TODO Auto-generated method stub this.addEventListener("updateTreeEvent",function():void{ trList.invalidateList(); }); } private function iconFunction(item:Object):*{ if(!item.children){ }else{ if(trList.isItemOpen(item)){ return trList.getStyle("folderOpenIcon"); }else{ return trList.getStyle("folderClosedIcon"); } } } ]]--> </fx:Script> <mx:Tree id="trList" x="174" y="81" labelField="name" width="281" height="218" itemRenderer="common.control.tree.TreeCheckBoxRender" dataProvider="{collection}" iconFunction="iconFunction"></mx:Tree> </s:Application>