前段时间,老大召唤,给个任务,研究一下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+" 个选项! "; for each(var item:Object in myCombox2.selectedItems){ info2.text+=ObjectUtil.toString(item)+" "; } } 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