2008-11-06 71 views
8

我正在使用一個組合框自定義項目渲染顯示自定義繪製,而不是默認的文本標籤顯示的項目。Flex的自定義項目渲染在下拉列表

也能正常工作的下拉列表中,但所顯示的項目(當列表關閉時)仍然是我的對象的文本表示。

有沒有辦法有顯示的項目呈現方式的一個下拉一樣嗎?

回答

9

默認情況下,你不能做到這一點。但是,如果擴展ComboBox,則可以輕鬆添加此功能。下面是一個簡單的例子,它是一個粗略的版本,可能需要測試/調整,但它顯示了你可以如何實現這一點。

package 
{ 
    import mx.controls.ComboBox; 
    import mx.core.UIComponent; 

    public class ComboBox2 extends ComboBox 
    { 
     public function ComboBox2() 
     { 
      super(); 
     } 

     protected var textInputReplacement:UIComponent; 

     override protected function createChildren():void { 
      super.createChildren(); 

      if (!textInputReplacement) { 
       if (itemRenderer != null) { 
        //remove the default textInput 
        removeChild(textInput); 

        //create a new itemRenderer to use in place of the text input 
        textInputReplacement = itemRenderer.newInstance(); 
        addChild(textInputReplacement); 
       } 
      } 
     } 

     override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { 
      super.updateDisplayList(unscaledWidth, unscaledHeight); 

      if (textInputReplacement) { 
       textInputReplacement.width = unscaledWidth; 
       textInputReplacement.height = unscaledHeight; 
      } 
     } 
    } 
} 
5

我試過上面的解決方案,但發現當combobox關閉時,selectedItem沒有顯示。被要求的代碼中的額外線的itemRenderer數據屬性綁定到將selectedItem:

  if (!textInputReplacement) { 
        if (itemRenderer != null) { 
          //remove the default textInput 
          removeChild(textInput); 

          //create a new itemRenderer to use in place of the text input 
          textInputReplacement = itemRenderer.newInstance(); 

          // ADD THIS BINDING: 
          // Bind the data of the textInputReplacement to the selected item 
          BindingUtils.bindProperty(textInputReplacement, "data", this, "selectedItem", true); 

          addChild(textInputReplacement); 
        } 
      } 
0

謝謝maclema和Maurits的德布爾。我加了一對夫婦更多的事情到這個類,使它適合我的需求:

  • 我推翻設定的itemRenderer因此,如果您通過設定的itemRenderer AS而不是MXML這會奏效。我將文本輸入替換代碼移至其自己的函數以避免重複。

  • 我爲'increaseW'和'increaseH'添加了setter,以便在必要時調整組合框的大小,因爲我的渲染器起初對於組合框來說太大了。

  • 我從textInputReplacement寬度減去25,因此不會永遠重複的下拉按鈕...可以更好地使用更多的東西的比例,以適應不同的皮膚和這樣。

代碼:

package 
{ 
import mx.binding.utils.BindingUtils; 
import mx.controls.ComboBox; 
import mx.core.IFactory; 
import mx.core.UIComponent; 

    public class ComboBox2 extends ComboBox 
    { 
     public function ComboBox2() 
     { 
       super(); 
     } 

     protected var textInputReplacement:UIComponent; 
     private var _increaseW:Number = 0; 
     private var _increaseH:Number = 0; 

    public function set increaseW(val:Number):void 
    { 
    _increaseW = val; 
    } 

    public function set increaseH(val:Number):void 
    { 
    _increaseH = val; 
    } 

    override public function set itemRenderer(value:IFactory):void 
    { 
    super.itemRenderer = value; 
    replaceTextInput(); 
    } 

     override protected function createChildren():void 
     { 
       super.createChildren(); 
    replaceTextInput(); 

     } 

     override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void { 

      unscaledWidth += _increaseW; 
      unscaledHeight += _increaseH; 

       super.updateDisplayList(unscaledWidth, unscaledHeight); 

       if (textInputReplacement) { 
         textInputReplacement.width = unscaledWidth - 25; 
         textInputReplacement.height = unscaledHeight; 
       } 
     } 

     protected function replaceTextInput():void 
     { 
     if (!textInputReplacement) { 
         if (this.itemRenderer != null) { 
           //remove the default textInput 
           removeChild(textInput); 

           //create a new itemRenderer to use in place of the text input 
           textInputReplacement = this.itemRenderer.newInstance(); 
           addChild(textInputReplacement); 

           // ADD THIS BINDING: 
          // Bind the data of the textInputReplacement to the selected item 
          BindingUtils.bindProperty(textInputReplacement, "data", this, "selectedItem", true); 

          addChild(textInputReplacement); 

         } 
       } 
     } 
    } 
} 
+0

你能幫助我://刪除默認爲textInput \t \t \t \t \t removeChild之(爲textInput); 對mx.core類型的值的隱式強制:ITextInput與不相關的類型flash.display:DisplayObject。 – 2016-08-25 06:52:43

-1

這可以更簡單地實現,如果你只是在尋找某種與CSS屬性自定義格式的文本。覆蓋「get selectedLabel():String」函數以返回要在文本框中顯示的任何字符串。如果您需要某種CSS,請在selectedLabel()方法中的textInput(this.textInput)上設置樣式。

0

我一直在尋找一種方式來做到這一點使用Spark組合框。

此線程對我非常有用,但到目前爲止,我國目前僅有如何使用MX做答案:組合框。我以爲我應該附加我的答案,如何使用spark組合框來做到這一點。

  1. 創建組合框
  2. 隱藏的一個新的皮膚和禁用爲textInput
  3. 插入自己的組件

這是皮膚會是什麼樣子:

<s:SparkSkin> 

    <... Lots of other stuff/> 

    <s:BorderContainer height="25"> 
     <WHATEVER YOU NEED HERE!/> 
    </s:BorderContainer> 

    <!-- Disable the textInput and hide it --> 
    <s:TextInput id="textInput" 
     left="0" right="18" top="0" bottom="0" 
     skinClass="spark.skins.spark.ComboBoxTextInputSkin" 

     visible="false" enabled="false"/> 


</s:SparkSkin> 

使用Spark ComboBox這個過程非常簡單,不需要你擴展ComboBox。

3

我已經將Dane的代碼進一步擴展了一點。在某些情況下,點擊沒有打開我的渲染器的下拉框,我注意到正常的Flex組合框皮膚沒有觸發。因此,在replaceTextInput()我添加了一些額外的事件偵聽器,並保存對用於顯示皮膚的ComboBox按鈕的引用。現在它的行爲就像普通的ComboBox一樣。

下面的代碼:

 
    package 
    { 
    import flash.events.Event; 
    import flash.events.KeyboardEvent; 
    import flash.events.MouseEvent; 

    import mx.binding.utils.BindingUtils; 
    import mx.controls.Button; 
    import mx.controls.ComboBox; 
    import mx.core.IFactory; 
    import mx.core.UIComponent; 
    import mx.events.DropdownEvent; 

    /** 
    * Extension of the standard ComboBox that will use the assigned 'itemRenderer' 
    * for both the list items and the selected item. 
    * 
    * Based on code from: 
    * http://stackoverflow.com/questions/269773/flex-custom-item-renderer-for-the-displayed-item-in-the-combobox 
    */ 
    public class ComboBoxFullRenderer extends ComboBox 
    { 
    protected var textInputReplacement:UIComponent; 
    private var _increaseW:Number = 0; 
    private var _increaseH:Number = 0; 


    /** 
    * Keeps track of the current open/close state of the drop down list. 
    */ 
    protected var _isOpen:Boolean = false; 

    /** 
    * Stores a reference to the 'Button' which overlays the ComboBox. Allows 
    * us to pass events to it so skins are properly triggered. 
    */ 
    protected var _buttonRef:Button = null; 


    /** 
    * Constructor. 
    */ 
    public function ComboBoxFullRenderer() { 
     super(); 
    } 


    /** 
    * Sets a value to increase the width of our ComboBox to adjust sizing. 
    * 
    * @param val Number of pixels to increase the width of the ComboBox. 
    */ 
    public function set increaseW(val:Number):void { 
     _increaseW = val; 
    } 

    /** 
    * Sets a value to increase the height of our ComboBox to adjust sizing. 
    * 
    * @param val Number of pixels to increase the height of the ComboBox. 
    */ 
    public function set increaseH(val:Number):void { 
     _increaseH = val; 
    } 


    /** 
    * Override the 'itemRenderer' setter so we can also replace the selected 
    * item renderer. 
    * 
    * @param value The renderer to be used to display the drop down list items 
    * and the selected item. 
    */ 
    override public function set itemRenderer(value:IFactory):void { 
     super.itemRenderer = value; 
     replaceTextInput(); 
    } 


    /** 
    * Override base 'createChildren()' routine to call our 'replaceTextInput()' 
    * method to replace the standard selected item renderer. 
    * 
    * @see #replaceTextInput(); 
    */ 
    override protected function createChildren():void { 
     super.createChildren(); 
     replaceTextInput(); 
    } 


    /** 
    * Routine to replace the ComboBox 'textInput' child with our own child 
    * that will render the selected data element. Will create an instance of 
    * the 'itemRenderer' set for this ComboBox. 
    */ 
    protected function replaceTextInput():void { 
     if (!textInputReplacement) { 
      if (this.itemRenderer != null && textInput != null) { 
       //remove the default textInput 
       removeChild(textInput); 

       //create a new itemRenderer instance to use in place of the text input 
       textInputReplacement = this.itemRenderer.newInstance(); 
       // Listen for clicks so we can open/close the drop down when 
       // renderer components are clicked. 
       textInputReplacement.addEventListener(MouseEvent.CLICK, _onClick); 
       // Listen to the mouse events on our renderer so we can feed them to 
       // the ComboBox overlay button. This will make sure the button skins 
       // are activated. See ComboBox::commitProperties() code. 
       textInputReplacement.addEventListener(MouseEvent.MOUSE_DOWN, _onMouseEvent); 
       textInputReplacement.addEventListener(MouseEvent.MOUSE_UP, _onMouseEvent); 
       textInputReplacement.addEventListener(MouseEvent.ROLL_OVER, _onMouseEvent); 
       textInputReplacement.addEventListener(MouseEvent.ROLL_OUT, _onMouseEvent); 
       textInputReplacement.addEventListener(KeyboardEvent.KEY_DOWN, _onMouseEvent); 

       // Bind the data of the textInputReplacement to the selected item 
       BindingUtils.bindProperty(textInputReplacement, "data", this, "selectedItem", true); 

       // Add our renderer as a child. 
       addChild(textInputReplacement); 

       // Listen for open close so we can maintain state. The 
       // 'isShowingDropdown' property is mx_internal so we don't 
       // have access to it. 
       this.addEventListener(DropdownEvent.OPEN, _onOpen); 
       this.addEventListener(DropdownEvent.CLOSE, _onClose); 

       // Save a reference to the mx_internal button for the combo box. 
       // We will need this so we can call its dispatchEvent() method. 
       for (var i:int = 0; i < this.numChildren; i++) { 
        var temp:Object = this.getChildAt(i); 
        if (temp is Button) { 
         _buttonRef = temp as Button; 
         break; 
        } 
       } 
      } 
     } 
    } 


    /** 
    * Detect open events on the drop down list to keep track of the current 
    * drop down state so we can react properly to a click on our selected 
    * item renderer. 
    * 
    * @param event The DropdownEvent.OPEN event for the combo box. 
    */ 
    protected function _onOpen(event:DropdownEvent) : void { 
     _isOpen = true; 
    } 


    /** 
    * Detect close events on the drop down list to keep track of the current 
    * drop down state so we can react properly to a click on our selected 
    * item renderer. 
    * 
    * @param event The DropdownEvent.CLOSE event for the combo box. 
    */ 
    protected function _onClose(event:DropdownEvent) : void { 
     _isOpen = false; 
    } 


    /** 
    * When we detect a click on our renderer open or close the drop down list 
    * based on whether the drop down is currently open/closed. 
    * 
    * @param event The CLICK event from our selected item renderer. 
    */ 
    protected function _onClick(event:MouseEvent) : void { 
     if (_isOpen) { 
      this.close(event); 
     } else { 
      this.open(); 
     } 
    } 


    /** 
    * React to certain mouse/keyboard events on our selected item renderer and 
    * pass the events to the ComboBox 'button' so that the skins are properly 
    * applied. 
    * 
    * @param event A mouse or keyboard event to send to the ComboBox button. 
    * 
    */ 
    protected function _onMouseEvent(event:Event) : void { 
     if (_buttonRef != null) { 
      _buttonRef.dispatchEvent(event); 
     } 
    } 
    } // end class 
    } // end package 
0

我發現改變渲染所選元素更簡單的方法。只有當您的元素繼承自Flex 4.0或更高版本中的TextInput類時,此類纔有效。

在Flex V4.5,在ComboBase.createChildren在行1177,你會發現,該類可定義爲textInput可以使用樣式鍵textInputClass傳遞:

// Mechanism to use MXFTETextInput. 
var textInputClass:Class = getStyle("textInputClass");    
if (!textInputClass || FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_0) 
{ 
    textInput = new TextInput(); 
} 
else 
{ 
    textInput = new textInputClass(); 
} 

只要改變這個鍵的值你的組合構造函數,現在你有你自己的渲染器selectedItem

public function ComboAvailableProfessor() 
{ 
    super(); 

    itemRenderer = new ClassFactory(ProfessorAvailableListItemRenderer); 
    setStyle('textInputClass', ProfessorAvailableSelectedListItemRenderer); 
} 

最後,你必須將data屬性在您的組合中selectedItem屬性綁定,以獲得顯示的數據。

override protected function createChildren():void 
{ 
    super.createChildren(); 

    BindingUtils.bindProperty(textInput, 'data', this, 'selectedItem', true); 
} 
相關問題