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.cs

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.cs:

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

 
posted @ 2014-04-16 19:21  互联网荒漠  阅读(3496)  评论(0编辑  收藏  举报