2008-11-06 49 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); 
} 
相关问题