如何根据通过键盘输入的子字符串选择mx:ComboBox项

时间:2013-10-14 06:44:55

标签: flex flex3

我正在使用<mx:ComboBox />,我想根据通过键盘输入的字符串选择匹配的项目。目前,<mx:ComboBox />仅根据第一个字符选择第一个匹配项。我希望自定义此功能。我无法找到执行匹配的KeyboardEvent侦听器,以便我可以覆盖它。

2 个答案:

答案 0 :(得分:1)

要自己执行此操作,您应该查看以下ComboBoxListBase类中的以下代码。 ListBaseComboBox组件用于其下拉列表的内容。

ComboBox似乎是将键盘输入推迟到下拉列表。然后,它会从下拉列表中侦听事件,以了解选择何时发生更改(作为键盘或鼠标输入的结果)。

Flex组件通常会覆盖名为keyDownHandler()的方法,以便在有焦点时处理键盘输入。从那里开始,我们遇到ComboBox line 2231

// Redispatch the event to the dropdown
// and let its keyDownHandler() handle it.

dropdown.dispatchEvent(event.clone());
event.stopPropagation();

现在,下拉列表中的keyDownHandler()将被执行。该方法有一个巨大的switch语句,其中default case语句on line 9197 of ListBase如下所示:

default:
{
    if (findKey(event.charCode))
        event.stopPropagation();
}

这是下拉列表根据键盘输入决定选择的内容(当输入不是箭头键或向上翻页时等)。受保护的findKey()方法只需调用公共findString()方法即可完成此项工作。

所以要自己覆盖这种行为:

  • 扩展ListBase类并使用您的自定义逻辑覆盖findKey()findString()方法
  • 扩展ComboBox类并覆盖createChildren()方法,以便您可以实例化自定义ListBase类而不是默认类。

答案 1 :(得分:1)

这是我为了使其发挥作用而使用的课程。 searchStr是用户输入的字符串,需要匹配。如果没有dataprovider项与searchStr匹配,则重写的侦听器将回退到默认行为。我使用Timer在2秒后刷新输入的searchStr。可能的缺点是假设数据提供者是String值的集合。但您可以根据需要对其进行相应修改。

public class CustomComboBox extends ComboBox
    {
        private var searchStr:String="";
        private var ticker:Timer;
        public function CustomComboBox()
        {
            super();
            ticker = new Timer(2000);
            ticker.addEventListener(TimerEvent.TIMER, resetSearchString);
        }

        override protected function keyDownHandler(event:KeyboardEvent):void
        {
            super.keyDownHandler(event);

            // code to search items in the list based on user input.
            // Earlier, the default behavior shows the matched items in the dropdown,  based on first character only.
            // user input is invisible to user.
            if((event.charCode>=0x20 && event.charCode<=0x7E) || event.charCode==8)             //Range of printable characters is 0x20[space] to 0x7E[~] in ASCII. 8 is ASCII code of [backspace].
            {
                ticker.reset();
                ticker.start();

                if(event.charCode==8)
                {
                    if(searchStr=="")
                        return;
                    searchStr = searchStr.substr(0, searchStr.length-1);
                }
                else
                {
                    searchStr += String.fromCharCode(event.charCode);
                    searchStr = searchStr.toLowerCase();
                }
                for each(var str:String in dataProvider)
                {
                    if(str.toLowerCase().indexOf(searchStr, 0)>-1)
                    {
                        this.selectedItem = dropdown.selectedItem = str;
                        dropdown.scrollToIndex(dropdown.selectedIndex);

                        break;
                    }
                }
            }
        }


        /**
         * reset the search string and reset the timer.
         **/ 
        private function resetSearchString(evt:TimerEvent):void
        {
            searchStr = "";
            ticker.reset();
        }
    }