Flex — ArrayCollection — добавление и удаление функции фильтрации

#flash #apache-flex #refresh #arraycollection #filterfunction

#flash #apache-гибкий #обновить #arraycollection #функция фильтра

Вопрос:

Я использую Adobe Flash Builder 4 Premium. У меня есть mx:DataGrid и s:TextInput , и я пытаюсь настроить окно поиска, которое фильтрует сетку данных при каждом нажатии клавиши.

На этой странице показан почти идеальный пример того, что я пытаюсь сделать, за исключением того, что я настраиваю это в s:TitleWindow , который выводится в виде всплывающего окна с помощью PopUpManager. Список, который я пытаюсь отфильтровать, может быть очень большим. Это список имен пользователей, извлекаемых из базы данных MySQL с помощью PHP. Поскольку он может быть таким большим, я хочу, чтобы список заполнялся один раз в главном приложении, а затем ссылался во всплывающем окне, чтобы ему не приходилось извлекать все имена пользователей каждый раз, когда пользователь открывает всплывающее окно.

У меня все это работает нормально при первом появлении всплывающего окна, но если вы закроете его и вызовете снова, я получу эту ошибку во время выполнения:

Ошибка во время выполнения Flash

Я также получаю эту ошибку, если пытаюсь вернуть filterFunction значение null непосредственно перед закрытием всплывающего окна.

Смотрите пример кода ниже:

Основное приложение:

 <?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx">
    <fx:Script>
        <![CDATA[
            import mx.collections.*;
            import mx.managers.PopUpManager;

            [Bindable] public var allMembersList:ArrayCollection;

            private function openPopup():void
            {
                var popupInstance:popup = PopUpManager.createPopUp(this as DisplayObject, popup, true) as popup;
                PopUpManager.centerPopUp(popupInstance);
            }
        ]]>
    </fx:Script>
    <s:Button label="Open Popup" click="openPopup()"/>
</s:Application>
  

Всплывающее окно:

 <?xml version="1.0" encoding="utf-8"?>
<s:TitleWindow 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:model="services.model.*"
               tabChildren="false"
               close="close()">
    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;
            import mx.core.FlexGlobals;
            import mx.managers.PopUpManager;

            private function getUsers(startsWith:String = ""):void
            {
                if (FlexGlobals.topLevelApplication.allMembersList == null)
                {
                    FlexGlobals.topLevelApplication.allMembersList = new ArrayCollection();
                    getUsersResult.token = php.getUsers();
                }

                FlexGlobals.topLevelApplication.allMembersList.filterFunction = function(item:Object):Boolean
                {
                    return item.username.match(new RegExp("^"  startsWith, "i"));
                };
                FlexGlobals.topLevelApplication.allMembersList.refresh();
                grdMemberList.dataProvider = FlexGlobals.topLevelApplication.allMembersList;
            }

            private function getUsersResultHandler():void
            {
                var users:Object = getUsersResult.lastResu<
                for each (var user:Object in users)
                    FlexGlobals.topLevelApplication.allMembersList.addItem({"username":user.username});
            }

            private function close():void
            {
                FlexGlobals.topLevelApplication.allMembersList.filterFunction = null;
                FlexGlobals.topLevelApplication.allMembersList.refresh();
                PopUpManager.removePopUp(this);
            }
        ]]>
    </fx:Script>
    <fx:Declarations>
        <model:MODEL id="php" fault="{Alert.show('There was a PHP error!nPlease note the steps taken to produce this error and call support.nnError Message: '  event.fault.faultDetail, 'Error');}" showBusyCursor="false"/>
        <s:CallResponder id="getUsersResult" result="getUsersResultHandler()"/>
    </fx:Declarations>

    <mx:DataGrid id="grdMemberList" creationComplete="getUsers()">
        <mx:columns>
            <mx:DataGridColumn headerText="Member List" dataField="username"/>
        </mx:columns>
    </mx:DataGrid>
    <s:TextInput id="txtUsername" keyUp="{ if (event.charCode != 13 amp;amp; event.charCode != 0) getUsers(txtUsername.text); }"/>
</s:TitleWindow>
  

Приложение, похоже, по-прежнему работает должным образом, несмотря на ошибку, но я не любитель ошибок в своем приложении, поэтому мне бы очень хотелось выяснить, что вызывает эту проблему.

Спасибо!

Комментарии:

1. Опубликованный мной код представляет собой небольшой отрывок из моего приложения, который я не тестировал перед его публикацией. Не похоже, что это приводит к такой ошибке для меня. Я продолжу просматривать свой код, чтобы посмотреть, смогу ли я сузить его, но пока, если у кого-нибудь есть какое-либо представление, основанное только на сообщении об ошибке, я был бы рад его услышать.

2. Ни один из элементов в этом стеке вызовов не ссылается на коллекцию массивов, все это касается отображаемых объектов, и последний — это попытка что-то скрыть. Я думаю, это может иметь какое-то отношение к вызову close =»закрыть()». Одна из моих мыслей заключается в том, что всплывающее окно удаляется со сцены перед выполнением обратного вызова.

3. Запустите свой код в режиме отладки, чтобы точно выяснить, что вызывает ошибку. Кроме того, вам может быть полезно опубликовать полную трассировку стека вместо ее скриншота.

4. Я все еще сбит с толку этим, но, похоже, проблема заключалась в том, что для свойства tabChildren у меня было установлено значение false для TitleWindow. Я делаю это для того, чтобы я мог самостоятельно управлять функциональностью табуляции без использования табуляции по умолчанию. Теперь, когда я рассмотрел это поближе, в документации говорится не использовать tabChildren в Flex, а вместо этого использовать hasFocusableChildren (что не работает). Не уверен, почему эта проблема проявилась только тогда, когда я начал настраивать приведенный выше сценарий, но есть ли у кого-нибудь способ отключить поведение клавиши TAB по умолчанию, чтобы я мог настроить его сам?

5. Не могли бы вы попробовать записать событие keydown или keyup, а затем вызвать метод preventDefault () для этого? Еще одна мысль, поскольку я слышал о проблемах, связанных с клавишей tab, заключалась бы в вызове функции SetFocus () сразу после захвата нажатия клавиши, чтобы предотвратить изменение фокуса до того, как вы сможете предотвратить функциональность по умолчанию.

Ответ №1:

Оказывается, проблема была в tabChildren свойстве. В документации сказано не использовать это свойство в Flex, а использовать hasFocusableChildren вместо этого. Не уверен, почему эта проблема проявилась только после того, как я попытался установить filterFunction .

Причина, по которой я установил tabChildren значение false, заключалась в том, что функциональность клавиши TAB по умолчанию (переключение фокуса) не выполнялась, чтобы я мог контролировать это поведение самостоятельно. hasFocusableChildren Свойство не работает (или, по крайней мере, установка для него значения false не мешает клавише TAB переключать фокус), поэтому мне, возможно, придется попробовать другой способ захвата события клавиши TAB и его остановки.


Редактировать:

Для всех, кто заинтересован (даже если это на самом деле не имеет никакого отношения к исходному сообщению), решение состояло в том, чтобы изменить:

 <s:TitleWindow 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:model="services.model.*"
               width="1000"
               height="550"
               tabChildren="false"
               close="close()">
  

Для:

 <s:TitleWindow 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:model="services.model.*"
               width="1000"
               height="550"
               keyFocusChange="{ event.preventDefault(); }"
               close="close()">
  

Ответ №2:

Я никогда не пытаюсь тестировать ваш код (потому что для этого также нужна серверная часть), но я думаю, вам не следует возвращать filterFunction значение null. В качестве альтернативы вы могли бы установить для нее функцию, которая всегда возвращает true .

 function defaultFilterFunc( item: Object ): Boolean { return true; }