8

我在组合框中使用自定义项目渲染器来显示自定义绘图而不是默认文本标签。

这适用于下拉列表,但显示的项目(当列表关闭时)仍然是我的对象的文本表示。

有没有办法让显示的项目以与下拉列表中相同的方式呈现?

4

6 回答 6

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;
            }
        }
    }
}
于 2008-11-11T13:23:46.450 回答
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);
                    }
            }
于 2009-11-23T09:42:49.020 回答
3

我进一步扩展了 Dane 的代码。在某些情况下,单击并没有用我的渲染器打开下拉框,我注意到正常的 Flex ComboBox 皮肤没有触发。因此,在replaceTextInput()中,我添加了一些额外的事件侦听器,并保存了对用于显示皮肤的 ComboBox 按钮的引用。现在它的行为就像普通的 ComboBox 一样。

这是代码:

    包裹
    {
    导入 flash.events.Event;
    导入 flash.events.KeyboardEvent;
    导入 flash.events.MouseEvent;

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

    /**
     * 标准组合框的扩展,将使用分配的“itemRenderer”
     * 用于列表项和选定项。
     *
     * 基于以下代码:
     * http://stackoverflow.com/questions/269773/flex-custom-item-renderer-for-the-displayed-item-in-the-combobox
     */
    公共类 ComboBoxFullRenderer 扩展 ComboBox
    {
    受保护的 var textInputReplacement:UIComponent;
    私人 var _increaseW:Number = 0;
    私有变量 _increaseH:Number = 0;


    /**
     * 跟踪下拉列表的当前打开/关闭状态。
     */
    受保护的 var _isOpen:Boolean = false;

    /**
     * 存储对覆盖组合框的“按钮”的引用。允许
     * 我们将事件传递给它,以便正确触发皮肤。
     */
    受保护的 var _buttonRef:Button = null;


    /**
     * 构造函数。
     */
    公共函数 ComboBoxFullRenderer() {
        极好的();
    }


    /**
     * 设置一个值来增加我们的 ComboBox 的宽度以调整大小。
     *
     * @param val 增加组合框宽度的像素数。
     */
    公共函数集增加W(val:Number):void {
        _increaseW = val;
    }

    /**
     * 设置一个值来增加我们的 ComboBox 的高度来调整大小。
     *
     * @param val 增加组合框高度的像素数。
     */
    公共函数集增加H(val:Number):void {
        _increaseH = 值;
    }


    /**
     * 覆盖 'itemRenderer' 设置器,这样我们也可以替换选定的
     * 项目渲染器。
     *  
     * @param value 用于显示下拉列表项的渲染器
     * 和所选项目。
     */
    覆盖公共函数集 itemRenderer(value:IFactory):void {
        super.itemRenderer = 值;
        替换文本输入();
    }


    /**
     * 覆盖基本的 'createChildren()' 例程来调用我们的 'replaceTextInput()'
     * 替换标准选定项渲染器的方法。
     *  
     * @see #replaceTextInput();
     */
    覆盖受保护的函数 createChildren():void {
        super.createChildren();
        替换文本输入();
    }


    /**
     * 用我们自己的孩子替换 ComboBox 'textInput' 孩子的例程
     * 这将呈现选定的数据元素。将创建一个实例
     * 为这个 ComboBox 设置的 'itemRenderer'。
     */
    受保护的函数replaceTextInput():void {
        如果(!textInputReplacement){
            if ( this.itemRenderer != null && textInput != null ) {
                //删除默认的文本输入
                removeChild(textInput);

                //创建一个新的 itemRenderer 实例来代替文本输入
                textInputReplacement = this.itemRenderer.newInstance();
                // 监听点击,以便我们可以在何时打开/关闭下拉菜单
                // 渲染器组件被点击。  
                textInputReplacement.addEventListener(MouseEvent.CLICK, _onClick);
                // 在我们的渲染器上监听鼠标事件,以便我们可以将它们提供给
                // ComboBox 覆盖按钮。这将确保按钮皮肤
                // 被激活。请参阅 ComboBox::commitProperties() 代码。
                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);

                // 将 textInputReplacement 的数据绑定到选中项
                BindingUtils.bindProperty(textInputReplacement, "data", this, "selectedItem", true);

                // 将我们的渲染器添加为子级。
                addChild(textInputReplacement);

                // 监听打开关闭,这样我们就可以保持状态。这
                // 'isShowingDropdown' 属性是 mx_internal 所以我们不
                // 可以访问它。
                this.addEventListener(DropdownEvent.OPEN, _onOpen);
                this.addEventListener(DropdownEvent.CLOSE, _onClose);

                // 保存对组合框的 mx_internal 按钮的引用。
                // 我们需要这个,所以我们可以调用它的 dispatchEvent() 方法。
                for (var i:int = 0; i < this.numChildren; i++) {
                    var temp:Object = this.getChildAt(i);
                    如果(温度是按钮){
                        _buttonRef = temp 作为按钮;
                        休息;
                    }
                }
            }
        }
    }


    /**
     * 检测下拉列表中的打开事件以跟踪当前
     * 下拉状态,以便我们可以对点击我们选择的点击做出正确反应
     * 项目渲染器。
     *  
     * @param event 组合框的 DropdownEvent.OPEN 事件。
     */
    受保护的功能_onOpen(事件:DropdownEvent):无效{
        _isOpen = 真;
    }


    /**
     * 检测下拉列表中的关闭事件以跟踪当前
     * 下拉状态,以便我们可以对点击我们选择的点击做出正确反应
     * 项目渲染器。
     *  
     * @param event 组合框的 DropdownEvent.CLOSE 事件。
     */
    受保护的功能_onClose(事件:DropdownEvent):无效{
        _isOpen = 假;
    }


    /**
     * 当我们检测到点击我们的渲染器打开或关闭下拉列表
     * 基于下拉菜单当前是否打开/关闭。
     *  
     * @param event 来自我们选择的项目渲染器的 CLICK 事件。
     */
    受保护的功能_onClick(事件:MouseEvent):无效{
        如果(_isOpen){
            this.close(事件);
        } 别的 {
            this.open();
        }
    }


    /**
     * 对我们选定的项目渲染器上的某些鼠标/键盘事件做出反应,并
     * 将事件传递给 ComboBox 'button' 以便皮肤正确
     * 应用。
     *  
     * @param event 要发送到 ComboBox 按钮的鼠标或键盘事件。
     *
     */
    受保护的功能_onMouseEvent(事件:事件):无效{
        if (_buttonRef != null) {
            _buttonRef.dispatchEvent(event);
        }
    }
    } // 结束类
    } // 结束包
于 2012-07-26T16:15:59.683 回答
0

谢谢 maclema 和 Maurits de Boer。我在这个类中添加了一些东西来满足我的需要:

  • 我覆盖了 set itemRenderer,因此如果您通过 AS 而不是 mxml 设置 itemRenderer,这将起作用。我将文本输入替换代码移到了它自己的函数中以避免重复。

  • 我为“increaseW”和“increaseH”添加了设置器,以便在必要时调整组合框的大小,因为我的渲染器起初对于组合框来说太大了。

  • 我从 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);

                        }
                }
        }
    }
}
于 2010-03-15T09:26:49.110 回答
0

我正在寻找一种使用 Spark ComboBox 的方法。

这个线程对我非常有用,但到目前为止,只有关于如何使用 mx:ComboBox 的答案。我认为我应该附加关于如何使用 spark ComboBox 的答案。

  1. 创建 ComboBox 的新皮肤
  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。

于 2011-10-12T18:13:17.027 回答
0

我找到了一种更简单的方法来更改所选元素的渲染器。TextInput仅当您的元素从Flex 4.0 或更高版本中的类继承时,此选项才有效。

在 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 );
}

最后,您必须将属性绑定dataselectedItem组合中的属性才能显示数据。

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

    BindingUtils.bindProperty( textInput, 'data', this, 'selectedItem', true );
}
于 2015-09-10T20:53:18.840 回答