Класс, реализующий IEventDispatcher, не может использовать тег метаданных события - PullRequest
0 голосов
/ 04 мая 2011

Хорошо, гуру Flex, у нас есть следующий класс

package
{
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IEventDispatcher;

    import mx.controls.Alert;
    import mx.core.IMXMLObject;

    [Event(name="progressReady", type="flash.events.Event")]
    public class IndependentClass implements IMXMLObject, IEventDispatcher{
            public var dispatcher:IEventDispatcher;

            public function initialized(document:Object, id:String):void{
                    dispatcher = document as EventDispatcher;
                    addEventListener("progressReady", progressReadyListener);
            }

            public function progressReadyListener(e:Event):void{
                    Alert.show("progressReadyListener inside");
            }

            public function click():void{
                    dispatchEvent(new Event("progressReady", true));
            }

            public function addEventListener(type:String, listener:Function, useCapture:Boolean=false, priority:int=0, useWeakReference:Boolean=false):void{
                    if(dispatcher != null){
                            dispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
                    }
            }

            public function dispatchEvent(event:Event):Boolean{
                    if(dispatcher != null){
                            return dispatcher.dispatchEvent(event);
                    }
                    return false;
            }

            public function hasEventListener(type:String):Boolean{
                    if(dispatcher != null){
                            return dispatcher.hasEventListener(type);
                    }
                    return false;
            }

            public function removeEventListener(type:String, listener:Function, useCapture:Boolean=false):void{
                    if(dispatcher != null){
                            dispatcher.removeEventListener(type, listener, useCapture);
                    }
            }

            public function willTrigger(type:String):Boolean{
                    if(dispatcher != null){
                            return dispatcher.willTrigger(type);
                    }
                    return false;
            }
       }

    }

И у нас есть следующая разметка MXML:

<?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" 
           xmlns:local="*">

<fx:Script>
    <![CDATA[
        import mx.controls.Alert;
        protected function progressHandler():void{
            Alert.show("progressHandler outside");
        }
    ]]>
</fx:Script>

<fx:Declarations>
    <local:IndependentClass id="ic" progressReady="progressHandler()"/>
</fx:Declarations>

<s:Button click="{ic.click()}"/>
</s:Application>

Если вы запустите их, вы заметите, что компонент MXMLне могу услышать событие.Вопрос прост: есть ли способ заставить тег Event-metadata работать БЕЗ расширения EventDispatcher?Я хотел бы сохранить этот класс независимым и максимально использовать композицию объектов.

И нет, я не хочу использовать ActionScript addEventListener в MXML-файле.Он не говорит разработчику ничего подобного старому доброму тегу метаданных Event, и, кроме того, это не главное в этом примере.:)

Будем надеяться, что кто-то сможет понять, что делает метаданные события за кулисами.

Ответы [ 2 ]

0 голосов
/ 04 мая 2011

Хорошо.Чтобы ваш код работал, ypu должен изменить ваш основной класс следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:local="*" xmlns:mx="library://ns.adobe.com/flex/mx"
    xmlns:s="library://ns.adobe.com/flex/spark" creationComplete="init()">

    <fx:Script>
    <![CDATA[
        import mx.controls.Alert;

        protected function progressHandler():void
        {
            Alert.show("progressHandler outside");
        }

        protected function init():void
        {
            addEventListener("progressReady", progressReadyHandler);
        }

        private function progressReadyHandler(event:Event):void
        {
            progressHandler();
        }
    ]]>
    </fx:Script>

    <fx:Declarations>
        <local:IndependentClass id="ic" />
    </fx:Declarations>

    <s:Button click="{ic.click()}" />
</s:Application>

Проблема в том, что вы не установили объект, который правильно отправляет события.В вашем случае этот объект все еще является основным классом приложения.Чтобы достичь своей цели, вы должны воссоздать ваш IndependentClass следующим образом:

package
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;

import mx.controls.Alert;

[Event(name="progressReady", type="flash.events.Event")]
public class ProperIndependentClass implements IEventDispatcher
{
    public function ProperIndependentClass()
    {
        // This line initialized dispatching making this object target and currentTarget of the event
        dispatcher = new EventDispatcher(this);
        addEventListener("progressReady", progressReadyListener);
    }

    private var dispatcher:EventDispatcher;

    public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0,
                                     useWeakReference:Boolean = false):void
    {
        dispatcher.addEventListener(type, listener, useCapture, priority);
    }

    public function click():void
    {
        dispatchEvent(new Event("progressReady", true));
    }

    public function hasEventListener(type:String):Boolean
    {
        return dispatcher.hasEventListener(type);
    }

    public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
    {
        dispatcher.removeEventListener(type, listener, useCapture);
    }

    public function willTrigger(type:String):Boolean
    {
        return dispatcher.willTrigger(type);
    }

    public function dispatchEvent(evt:Event):Boolean
    {
        return dispatcher.dispatchEvent(evt);
    }

    public function progressReadyListener(e:Event):void
    {
        Alert.show("progressReadyListener inside");
    }
}
}

Я прокомментировал строку в конструкторе, который выполняет всю магию.Более подробная информация доступна в официальной документации .

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

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:local="*" xmlns:mx="library://ns.adobe.com/flex/mx"
    xmlns:s="library://ns.adobe.com/flex/spark">

    <fx:Script>
    <![CDATA[
        import mx.controls.Alert;

        protected function progressHandler():void
        {
            Alert.show("progressHandler outside");
        }
    ]]>
    </fx:Script>

    <fx:Declarations>
        <local:ProperIndependentClass id="ic" progressReady="progressHandler()" />
    </fx:Declarations>

    <s:Button click="{ic.click()}" />
</s:Application>

А как насчет [Event] метатег.Это не что иное, как аннотация времени компиляции, которая помогает компилятору проверять атрибуты тегов MXML.Другое использование этого метатега - это завершение кода событий в IDE (как в MXML, так и в ActionScript при вводе addEventListener).Это не имеет никакого влияния во время выполнения.

PS И Джеффри прав, говоря, что вы должны просто расширить EventDispatcher.Цель IEventDispatcher состоит в том, что ваш класс наследует какой-то другой класс, который не является производным от EventDispatcher.В этом случае вы можете использовать композицию для решения проблемы диспетчеризации событий.В вашем случае ваш IndependentClass не имеет требований не наследовать от EventDispatcher.

0 голосов
/ 04 мая 2011

Метка метаданных события для работы БЕЗ расширения EventDispatcher

Насколько я знаю, метаданные события делают только две вещи.Он сообщает коду, подсказывающему, что компонент может отправить событие;или он используется для генерации ASDocs.Я ожидаю, что вы сможете использовать метаданные без расширения EventDispatcher;однако я не верю, что ваш компонент сможет отправлять событие без расширения EventDispatcher или создания собственной системы Event Dispatcher.Я считаю AS3 Signals альтернативной системой диспетчеризации событий.

Я не хочу использовать ActionScript addEventListener в MXML-файле.Он не говорит разработчику ничего, как старый добрый тег метаданных события,

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

Я считаю, что это отвечает на ваши вопросы.Мой личный подход заключается в расширении EventDispatcher, если класс должен отправлять события.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...