Проблема с отправкой пользовательского события в FLEX - PullRequest
0 голосов
/ 13 февраля 2009

Позвольте мне начать с того, что я довольно новичок в сценарии flex и action. В любом случае, я пытаюсь создать пользовательское событие, чтобы взять выбранного сотрудника и заполнить форму. Событие отправляется (dispatchEvent (event) возвращает true), но точки останова, установленные внутри обработчика, никогда не достигаются.

Вот некоторые фрагменты моего кода (логически организованные для лучшего понимания):

Пользовательский компонент формы сотрудника

<mx:Metadata>
     [Event(name="selectEmployeeEvent", type="events.EmployeeEvent")]
<mx:Metadata>
<mx:Script>
   [Bindable]
   public var selectedEmployee:Employee;
</mx:Script>
...Form Fields

Применение

<mx:DataGrid id="grdEmployees" width="160" height="268"
            itemClick="EmployeeClicked(event);">
<custom:EmployeeForm
     selectEmployeeEvent="SelectEmployeeEventHandler(event)"
     selectedEmployee="{selectedEmployee}" />

<mx:Script>
    [Bindable]
private var selectedEmployee:Employee;

private function EmployeeClicked(event:ListEvent):void
    {
     var employeeData:Employee;
     employeeData = event.itemRenderer.data as Employee;
     var employeeEventObject:EmployeeEvent = 
             new EmployeeEvent( "selectEmployeeEvent", employeeData);
     var test:Boolean = dispatchEvent(employeeEventObject);
         //test == true in debugger
}
    private function SelectEmployeeEventHandler(event:EmployeeEvent):void
    {
         selectedEmployee = event.Employee; //This event never fires
    }



</mx:Script>

Ответы [ 2 ]

3 голосов
/ 13 февраля 2009

Есть несколько вещей, которые могут привести к неприятностям. :)

Во-первых, это объявление в вашем пользовательском компоненте:

<mx:Metadata>
     [Event(name="selectEmployeeEvent", type="events.EmployeeEvent")]
<mx:Metadata>

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

Другое дело, что в ситуациях выбора элементов списка, подобных этой, более типичным является извлечение объекта из свойства selectedItem объекта currentTarget объекта ListEvent (т. Е. Вашей сетки - и currentTarget, а не цели). из-за способа всплывающего события работает). В вашем случае свойство selectedItem сетки должно содержать объект Employee (при условии, что dataProvider вашей сетки представляет собой ArrayCollection объектов Employee), поэтому вы должны ссылаться на него напрямую следующим образом:

private function employeeClicked(event:ListEvent):void
{
   var employee:Employee = event.currentTarget.selectedItem as Employee;
   dispatchEvent(new EmployeeEvent("selectEmployeeEvent"), employee);
}

Использование itemRenderer в качестве источника данных является общеизвестно ненадежным, поскольку средства визуализации элементов являются визуальными элементами, которые повторно используются платформой способами, которые вы не всегда можете предсказать. Вместо этого гораздо безопаснее извлечь элемент из события напрямую, как я продемонстрировал выше - в этом случае вам вообще не понадобится объект employeeData, поскольку у вас уже будет объект Employee.

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

<mx:Script>
    <![CDATA[

        import mx.events.ListEvent;

        [Bindable]
        private var selectedEmployee:Employee;

        private function dgEmployees_itemClick(event:ListEvent):void
        {
            selectedEmployee = event.currentTarget.selectedItem as Employee;
        }

    ]]>
</mx:Script>

<mx:DataGrid id="dgEmployees" dataProvider="{someArrayCollectionOfEmployees}" itemClick="dgEmployees_itemClick(event)" />

<custom:EmployeeForm selectedEmployee="{selectedEmployee}" />

... вы бы определили элемент selectedEmployee, помеченный как Bindable, который вы устанавливаете в обработчике itemClick в DataGrid. Таким образом, выражение привязки, указанное вами в EmployeeForm, гарантирует, что форма всегда будет иметь ссылку на выбранного сотрудника. Тогда в самой форме:

<mx:Script>
    <![CDATA[

        [Bindable]
        [Inspectable]
        public var selectedEmployee:Employee;

    ]]>
</mx:Script>

<mx:Form>
    <mx:FormItem label="Name">
        <mx:TextInput text="{selectedEmployee.name}" />
    </mx:FormItem>
</mx:Form>

... вы просто принимаете выбранного сотрудника (который снова помечается как привязываемый, чтобы в полях формы всегда была самая свежая информация об этом выбранном сотруднике).

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

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

yourContainingDoc.addEventListener("selectEmployeeEvent", yourOtherComponentsSelectionHandler);

Надеюсь, это поможет - не стесняйтесь оставлять комментарии, и я буду следить.

1 голос
/ 13 февраля 2009

Вы отправляете событие из класса в нижнем примере кода (я думаю, DataGrid), но событие определено в классе EmployeeForm, и обработчик событий также присоединен к экземпляру EmployeeForm. Насколько мне известно, события распространяются вверх по иерархии, а не вниз, поэтому, когда вы запускаете событие от родителя формы, оно никогда не будет запускать обработчики в самой форме. Либо запустите событие из формы, либо присоедините обработчик события к родительскому компоненту.

...