Flex 扩展combobox 实现复选功能

原文: Flex 扩展combobox 实现复选功能

     前段时间,老大召唤,给个任务,研究一下flex的combobox控件 实现复选功能(flex自带的combobox控件不可以复选),小兵能力有限,哪里可以扩展呀,网上看了别人写的,发现总是有点瑕疵(关键是还没有注释这个是最蛋疼的):

     1.静态数据源正常,动态数据源 第一次点击时 没有取到数据,下拉列表为空。

     2. ROLL_OVER  ROLL_OUT 监听混乱,选择一项后下拉框突然收缩了,或者选择几项下拉框突然收缩了。

     3.返回值有误,显示选中的项 与 实际返回选中的项不符

分析:

  ROLL_OVER 与 ROLL_OUT 区别:

  ROLL_OVER:就是鼠标从外部移入该组件才调用, ROLL_OUT 就是鼠标移到该组件外部才调用

另外 其他两个:MOUSE_OVER 与MOUSE_OUT 区别类似

  ROLL_* 与MOUSE_* 的区别是:

    MOUSE_*:鼠标 进入/移 出该组件时会调度MOUSE_*事件,即使是从其子组件移到该组件依然会触发该事件

    ROLL_* :鼠标从不是其子组件的其余组件中进入该组件时会调度ROLL_*事件

下面是扩展后的代码:

必要部分已经加上了注释

MultipleComboBox

package common

{

    import flash.events.Event;

    import flash.events.MouseEvent;

    

    import mx.collections.ArrayCollection;

    import mx.controls.ComboBox;

    import mx.core.ClassFactory;

    import mx.events.FlexEvent;

    import mx.events.ListEvent;  

  

    public class MultipleComboBox extends ComboBox{  

        private var mouseOut:Boolean=false;

       [Bindable]  

        private var promptText:String="";   //复选框收缩后显示label的值

        private var selArr:Array=[];         //复选框选中值集合

        private var splitStr:String="/";    //选中多个值 以此分割

       public function MultipleComboBox(){  

            super();  

            this.addEventListener(FlexEvent.CREATION_COMPLETE,onCreateCompleteHandle);

            //多选ComboBox 内嵌CheckBox实现

            this.itemRenderer=new ClassFactory(CheckBoxItemRenderer);             

        }  

        private function onCreateCompleteHandle(event:FlexEvent):void{

            dropdown.allowMultipleSelection=true; 

            close(); 

            //

            mouseOut=false; //置为false

        }  

        //监听鼠标一入一出

        private function initListener():void{  

            if(!dropdown.hasEventListener(MouseEvent.ROLL_OVER))  

                dropdown.addEventListener(MouseEvent.ROLL_OVER,onRollOverHandle);  

            if(!dropdown.hasEventListener(MouseEvent.ROLL_OUT))  

                dropdown.addEventListener(MouseEvent.ROLL_OUT,onRollOutHandle);  

        }

        private function onRollOverHandle(event:MouseEvent):void{  

            mouseOut=false;  

        }  

        private var changeEvent:ListEvent;  

        //ROLL_OUT 更改选中值集合

        private function onRollOutHandle(event:MouseEvent):void{ 

            var list:ArrayCollection=ArrayCollection(this.dataProvider);

            mouseOut=true;  

            var selectedStr:String = "";  //复选框收缩后的label,此处以"/"分割显示选中的值

            selArr=[];//每次清空selArr保存的值

            for each(var obj:Object in list)  //遍历数据源,向selArr数组添加状态selected=true(选中)的值

            {    

                if(obj.selected){

                    selectedStr += obj.Code+this.splitStr;

                    selArr.push(obj);

                }        

            }

            this.selectedItems=selArr;

            this.promptText = selectedStr.substring(0,selectedStr.length -1) ;  

            

            close(); //鼠标移出 收缩 

            //

            mouseOut=false; //置为false

            

            changeEvent= new ListEvent( ListEvent.CHANGE )  

            dispatchEvent( changeEvent);

            trace(this.text);

        }  

        //ComboBox 带有selectedItems属性 但只实现selectedItem,此处实现selectedItems

        public function set selectedItems(value:Array):void{  

            if (dropdown){  

                dropdown.selectedItems=value;

            }

            this.selArr=value;

        }  

  

        [Bindable("change")]  

        public function get selectedItems():Array{ 

            return selArr; 

       } 

        override public function close(trigger:Event=null):void{  

            //initListener();  

            if (mouseOut){  

                super.close(trigger);  

            }  

            this.textInput.text=promptText; 

            this.toolTip = promptText;

            initListener();//此处需要从上面注释处调整到这里,

            //因为 CheckBoxItemRender中的 this.addEventListener(Event.CHANGE,onClickCheckBox)监听导致

            //基数次单击时mouseOut=true; 直接下拉框收缩

        }  

        override public function set prompt(value:String):void{  

            promptText=value;  

        }  

        public function set split(value:String):void

        {

            this.splitStr=value;

        }

        public function get split():String

        {            

            return splitStr;

        }

    }  

}

CheckBoxItemRenderer:

package common

{

    import flash.events.Event;

    

    import mx.collections.ArrayCollection;

    import mx.controls.CheckBox;

    import mx.controls.List;

    import mx.utils.ArrayUtil;

    

    import configuration.FormatConfig;

    

    public class CheckBoxItemRenderer extends CheckBox{

        

        /**存储当前列数据对象**/

        private var currData:Object; 

        

        public function CheckBoxItemRenderer(){

            super();

            this.addEventListener(Event.CHANGE,onClickCheckBox);

        }

        

        override public function set data(value:Object):void{

            if(value !=null)

            {

                this.selected = value.selected;

                this.currData = value; 

                //此处CheckBox label显示code+name 可根据需要置

                this.label=value.Code+"  "+value.Name;   

            }

            else

            {

                this.label=null;

            }

        }

        //此属性可设置 数据源任意一项不可选 (enabled)

        override public function set enabled(value:Boolean):void{  //

            if(currData){

                value=currData.enabled==false?false:true;

            }

            super.enabled=value;

        }

        /*更改被选中项的状态selected=true*/

        private function onClickCheckBox(e:Event):void{    

            var list:ArrayCollection=ArrayCollection(List(this.parent.parent).dataProvider);//获取数据源

            for each(var obj:Object in list)

            {

                //label的值为数据源中code + name 拼接的 所以此处判断某一项是否被选中的条件看上去有点怪

                if((obj.Code+"  "+obj.Name)==this.label){ 

                    if(this.selected){

                        obj.selected=true;   //选中状态selected=true

                    }else{

                        obj.selected=false;  //为选好

                    }

                    //break;

                }

            }

        }

    }

}

由于扩展的不够通用,所以使用的时候稍微做点处理

应用 Temp.mxml文件

<?xml version="1.0" encoding="utf-8"?>

<mx:Module  xmlns:fx="http://ns.adobe.com/mxml/2009" 

            xmlns:s="library://ns.adobe.com/flex/spark" 

            xmlns:mx="library://ns.adobe.com/flex/mx"

            xmlns:common="common.*"

            creationComplete="module_creationCompleteHandler(event)"

            xmlns:mywebservice="services.mywebservice.*">

    <fx:Script>

        <![CDATA[

            import mx.rpc.soap.WebService;

            import spark.components.Scroller;

            import spark.components.VScrollBar;

            import spark.events.IndexChangeEvent;

            

            [Bindable]

            private var datacbbSource:ArrayCollection;

            

            private function ShowSelectItems2():void{

                info2.text="";

                info2.text+="选中了 "+myCombox2.selectedItems.length+" 个选项!\n";

                for each(var item:Object in myCombox2.selectedItems){

                    info2.text+=ObjectUtil.toString(item)+"\n";

                }

            }

            

            var num=0;

            private function module_creationCompleteHandler(event:FlexEvent):void 

            {

                GetDataResult.token = mywebservice.GetData(); //获取数据源

            }

            

            [Bindable]

            private var dataGrideSource:ArrayCollection;

            

            protected function GetAllShopsResult_resultHandler(event:ResultEvent):void

            {

                // TODO Auto-generated method stub

                var result:ArrayCollection=event.result as ArrayCollection;

                if (result == null || result.length == 0)

                {                

                    return;

                }

                this.datacbbSource=new ArrayCollection();
for each(var item in result) { datacbbSource.addItem({Code:item.Code,Name:item.Name,selected:false}); } } ]]> </fx:Script> <fx:Declarations> <s:CallResponder id="GetDataResult" result="GetDataResult_resultHandler(event)" /> <shopservice:MyWebService id="mywebService" /> </fx:Declarations> <s:VGroup width="100%" height="100%" paddingLeft="10" paddingRight="10" paddingBottom="10" paddingTop="3"> <s:HGroup width="100%" color="black" verticalAlign="middle" height="296"> <common:MultipleComboBox width="200" id="myCombox2" split=";" prompt="请选择" > <s:ArrayCollection list="{datacbbSource}"/> </common:MultipleComboBox> <mx:Text id="info2"/> <s:Button label="点击查看选择数据" click="ShowSelectItems2()"/> </s:HGroup> </s:VGroup> </mx:Module >

运行结果就不上图了,下面这段

for each(var item in  result)

{

     datacbbSource.addItem({Code:item.Code,Name:item.Name,selected:false});

}

对数据源做了处理,强制转换成含有Code,Name,selected(默认值false)三个属性的对象,因为在CheckBoxItemRenderer.cs 和MultipleComboBox.cs文件中,
使用到的参数直接使用到了Code,Name,selected属性。最后虽然最终这个没有应用到项目中,为了以后用到时方便,记录一下。

继续充电中。。。。

扩展代码参考:http://liu-yi126.iteye.com/blog/1305494

 

你可能感兴趣的:(combobox)