Flex中带有三种状态CheckBox的Tree的实现

常常会用到带有3种状态CheckBox的树形组件,比如在权限管理中,或者是地区选择中等等,如下图:


不多说费话了,直接进入主题,看看如何实现。其实在Flex中,只用自己实现一个TreeItemRenderer就可以了,代码如下:
package com.robin  {
    import flash.events.Event;
    import flash.geom.Rectangle;
    
    import mx.controls.CheckBox;
    import mx.controls.treeClasses.TreeItemRenderer;
    import mx.controls.treeClasses.TreeListData;
    import mx.events.FlexEvent;

    public class ThreeStatusCheckBoxTreeItemRenderer extends TreeItemRenderer 
{
        private static 
var _colorForThirdState:int = 0x37BEF8;
        private static 
var _selectedField:String = "selected";
        
        private 
var checkBox:CheckBox;

        public 
function ThreeStatusCheckBoxTreeItemRenderer() {
            super();
        }


        override protected 
function createChildren():void {
            super.createChildren();
            checkBox 
= new CheckBox();
            addChild(checkBox);
            checkBox.addEventListener(Event.CHANGE, changeHandler);
        }


        
/**//**
         * Initial data when component initialization
         *
         
*/

        override protected 
function commitProperties():void {
            super.commitProperties();
            
if (data && data.@[_selectedField] != null{
                
var s:int = int(data.@[_selectedField]);
                
var selected:Boolean = s > 0 ? true : false;
                checkBox.selected 
= selected;
            }
 else {
                checkBox.selected 
= false;
            }

        }


        
/**//**
         * update dataProvider when user click CheckBox
         *
         
*/

        protected 
function changeHandler(event:Event):void {
            
if (data && data.@[_selectedField] != null{
                data.@[_selectedField] 
= checkBox.selected ? "1" : "0";
            }

            
            
var listData:TreeListData = TreeListData(listData);
            
if (listData.hasChildren) {
                
var item:XML = XML(listData.item);
                handleAllChildren(item.children());
            }

            handleAllParents(listData.item.parent());
        }


        private 
function handleAllChildren(children:XMLList):void {
            
for each (var item:XML in children) {
                item.@[_selectedField] 
= checkBox.selected ? "1" : "0";
                
var children:XMLList = item.children();
                
if (children.length() > 0{
                    handleAllChildren(children);
                }

            }

        }


        private 
function handleAllParents(parent:XML):void {
            
if (parent != null{
                
var children:XMLList = parent.children();
                
var hasSelected1:Boolean = false;
                
var hasSelected2:Boolean = false;
                
var hasSelected0:Boolean = false;
                
for each (var item:XML in children) {
                    
if (int(item.@[_selectedField]) == 1{
                        hasSelected1 
= true;
                    }

                    
if (int(item.@[_selectedField]) == 2{
                        hasSelected2 
= true;
                    }

                    
if (int(item.@[_selectedField]) == 0{
                        hasSelected0 
= true;
                    }

                }

                
if (checkBox.selected == true{
                    
if (!hasSelected0 && !hasSelected2) {
                        parent.@[_selectedField] 
= "1";
                    }
 else {
                        parent.@[_selectedField] 
= "2";
                    }

                }
 else {
                    
if (!hasSelected1 && !hasSelected2) {
                        parent.@[_selectedField] 
= "0";
                    }
 else {
                        parent.@[_selectedField] 
= "2";
                    }

                }

                handleAllParents(parent.parent());
            }

        }


        
/**//**
         * reset itemRenderer's width
         
*/

        override protected 
function measure():void {
            super.measure();
            measuredWidth 
+= checkBox.getExplicitOrMeasuredWidth();
        }


        
/**//**
         * re-assign layout for tree, move lable to right
         * @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();

            
var node:XML = data as XML;
            
if (int(node.@[_selectedField]) == 2{
                fillCheckBox(
true);
            }
 else {
                fillCheckBox(
false);
            }


        }

        
        
/**//**
         * re-draw check box for the third state
         * @param isFill
         
*/

        private 
function fillCheckBox(isFill:Boolean):void {
            checkBox.validateNow();
            checkBox.graphics.clear();
            
if (isFill) {
                
var myRect:Rectangle = checkBox.getBounds(checkBox);
                checkBox.graphics.beginFill(_colorForThirdState, 
1);
                checkBox.graphics.drawRoundRect(myRect.x, myRect.y, myRect.width, myRect.height, 
10x00FF00);
                checkBox.graphics.endFill();
            }

        }



    }

}

然后在tree组件中使用这个renderer就可以了。
<? 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 "  xmlns:robin = " com.robin.* " >
    
< fx:Declarations >
        
< fx:XMLList id = " treeData " >
            
< node name  =   " ShangHai "  type = " ROOT "  selected  = " 1 " >
                
< node name  =   " HuangPu "  type = " NODE "  selected  =   " 1 " >
                    
< node name  =   " A "  type = " NODE "  selected  =   " 1 "   />
                    
< node name  =   " B "  type = " NODE "  selected  =   " 1 "   />
                
</ node >
                
< node name  =   " PuDong "  type = " NODE "  selected  =   " 1 " />
            
</ node >
            
< node name  =   " Beijing "  type = " ROOT "  selected  =   " 2 " >
                
< node name  =   " HaiDian "  type = " NODE "  selected  =   " 0 " />
                
< node name  =   " ChaoYang "  type = " NODE "  selected  =   " 1 " />
            
</ node >
        
</ fx:XMLList >
    
</ fx:Declarations >
    
< fx:Script >
        
<! [CDATA[
            protected 
function  getCurrentData_clickHandler(event:MouseEvent): void   {
                currentText.text 
= String(treeData);
            }

        ]]
>
    
</ fx:Script >
    
    
< mx:Tree x  =   " 0 "  y  =   " 0 "  width  =   " 232 "  height  =   " 285 "  itemRenderer  =   " com.robin.ThreeStatusCheckBoxTreeItemRenderer "  labelField  =   " @name "  dataProvider  =   " {treeData} " />
    
< s:Button x  =   " 43 "  y  =   " 293 "  label  =   " Get Current Data "  id  =   " getCurrentData "  click  =   " getCurrentData_clickHandler(event) " />
    
< s:TextArea x  =   " 253 "  y  =   " 0 "  width  =   " 459 "  height  =   " 285 "  id  =   " currentText " />
</ s:Application >

就是这么简单!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值