前段時間,老大召喚,給個任務,研究一下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