Flex - ArrayCollection - добавление и удаление функции filterFunction - PullRequest
2 голосов
/ 13 июня 2011

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

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

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

Flash runtime error

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

См. Пример кода ниже:

Основное применение:

<?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.lastResult;
                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.\n\nError 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 && event.charCode != 0) getUsers(txtUsername.text); }"/>
</s:TitleWindow>

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

Спасибо!

Ответы [ 2 ]

1 голос
/ 14 июня 2011

Оказывается, проблема была в свойстве 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()">

до:

<code><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()">
0 голосов
/ 14 июня 2011

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

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