Обработка щелчка мышью в списке Flex 4, чтобы найти выбранный элемент (так как itemClick ушел) - PullRequest
3 голосов
/ 08 декабря 2011

Я подготовил упрощенный тестовый пример для моего вопроса.Он сразу же запустится в вашем Flash Builder, если вы поместите в проект 2 файла, указанные ниже.

Я пытаюсь отобразить список строк и флажок подтверждения во всплывающем окне:

screenshot

В реальном приложении я отправляю пользовательское событие со строкой, выбранной в списке, но в тестовом коде ниже я просто вызываю trace (str);

Моя проблема: если я использую событие click , окно закрывается, даже если я нажимаю на полосу прокрутки (проверка ! Str ниже не помогает, когда элемент был выбран в предыдущем использовании).И если я использую событие change , окно не закрывается, когда я нажимаю на тот же элемент, что и в прошлый раз.И, кажется, itemClick событие больше не присутствует в spark.components.List .

Есть предложения, пожалуйста, о том, как решить эту, вероятно, частую проблему?

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

Test.mxml: (пожалуйста, нажмите myBtn несколько раз - чтобы увидеть мои проблемы с click и change )

<?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" 
    minWidth="400" minHeight="300">

    <fx:Script>
        <![CDATA[
            import mx.managers.PopUpManager;

            private var _popup:Popup = new Popup();

            private function showPopup(event:MouseEvent):void {
                PopUpManager.addPopUp(_popup, this, true);
                PopUpManager.centerPopUp(_popup);
            }
        ]]>
    </fx:Script>

    <s:Button id="myBtn" right="5" bottom="5" 
        label="Open window" click="showPopup(event)" />

</s:Application>

Popup.mxml:

<?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"
    width="240" height="240"
    creationComplete="init(event)"
    close="close()">    

    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayList;
            import mx.controls.Alert;
            import mx.events.FlexEvent;
            import mx.events.CloseEvent;
            import mx.events.ItemClickEvent;
            import mx.managers.PopUpManager;

            private var myData:ArrayList = new ArrayList();

            private function init(event:FlexEvent):void {
                // XXX in the real app data is updated from server
                myData.removeAll();
                for (var i:uint = 1; i <= 10; i++)
                    myData.addItem('Item #' + i);
            }

            public function close(event:TimerEvent=null):void {
                PopUpManager.removePopUp(this);
            }

            private function handleClick(event:MouseEvent):void {
                var str:String = myList.selectedItem as String;
                if (!str)
                    return;

                if (myBox.selected) {
                    Alert.show(
                        'Select ' + str + '?', 
                        null, 
                        mx.controls.Alert.YES | mx.controls.Alert.NO,
                        null,
                        handleConfirm,
                        null,
                        mx.controls.Alert.NO
                    );
                } else {
                    sendEvent();
                }
            }

            private function handleConfirm(event:CloseEvent):void {
                if (event.detail == mx.controls.Alert.YES)
                    sendEvent();
            }

            private function sendEvent():void {
                close();
                // XXX in the real app dispatchEvent() is called
                trace('selected: ' + (myList.selectedItem as String));
            }
        ]]>
    </fx:Script>

    <s:VGroup paddingLeft="20" paddingTop="20" 
            paddingRight="20" paddingBottom="20" gap="20" 
            width="100%" height="100%">
        <s:List id="myList" dataProvider="{myData}" 
            click="handleClick(event)"
            width="100%" height="100%" fontSize="24" />
        <s:CheckBox id="myBox" label="Confirm" />
    </s:VGroup>
</s:TitleWindow>

Также мне интересно, почему я получаю предупреждение выше:

Data binding will not be able to detect assignments to "myData".

Ответы [ 3 ]

5 голосов
/ 08 декабря 2011

Spark List отправляет ' IndexChangeEvent .CHANGE'. Вы можете прослушать это событие, чтобы узнать, когда выбор в Списке изменился.

    <s:List id="myList" dataProvider="{myData}" 
            change="handleIndexChange()"
            width="100%" height="100%" fontSize="24" />

Это событие отправляется только всякий раз, когда выбранный индекс действительно изменяется, что означает, что при повторном открытии окна элемент все еще может быть выбран, и при нажатии на него событие CHANGE не будет запущено. Чтобы это исправить, просто отмените выбор, прежде чем закрыть окно:

        public function close():void {
            myList.selectedIndex = -1;
            PopUpManager.removePopUp(this);
        }

Также убедитесь, что отправили событие с выбранным элементом до того, как закроете окно (и отмените его выбор).

Что касается вашего вопроса об обязательном предупреждении: вы получаете это сообщение, потому что вы не пометили «myData» как привязываемые. Чтобы это исправить, просто используйте тег [Bindable]:

[Bindable]
private var myData:ArrayList = new ArrayList();

или вообще пропустите привязку, если она вам не нужна, и просто назначьте поставщик данных в списке в ActionScript:

myList.dataProvider = myData;
2 голосов
/ 08 декабря 2011

Я бы порекомендовал два решения, если вы абсолютно не хотите отображать, какой элемент был выбран.В противном случае решение, предоставленное RIAStar , сработает.

Прослушивание событий rendererAdd и rendererRemove в вашем PopUp

Как объяснено здесь , выможет легко получить доступ к средствам визуализации вашего списка, не вмешиваясь в его бизнес virtualLayout.

Использовать настраиваемое средство визуализации

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

0 голосов
/ 08 декабря 2011

В вашем Test.mxml измените коды так:

  <fx:Script>
            <![CDATA[
                import mx.managers.PopUpManager;

                private var _popup:Popup;

                private function showPopup(event:MouseEvent):void {
                    _popup = new Popup();
                    PopUpManager.addPopUp(_popup, this, true);
                    PopUpManager.centerPopUp(_popup);
                }
            ]]>
        </fx:Script>

А в вашем Popup.mxml я не уверен, почему у вас есть TimerEvent в функции закрытия.Также трассировка не будет отображаться, так как вы вызываете функцию close () сразу после нажатия кнопки YES оповещения ..

...