在FLEX中调度自定义事件的问题

时间:2009-02-13 09:02:58

标签: flex events actionscript mxml

首先让我说我对flex和动作脚本很新。无论如何,我正在尝试创建一个自定义事件来接受选定的员工并填充表单。正在调度该事件(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 个答案:

答案 0 :(得分:3)

有一些事情在这里引起麻烦。 :)

首先,您的自定义组件中的此声明:

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

...向编译器宣布您的自定义组件调度此特定事件,但您实际上是使用包含文档而非自定义组件调度它 - 因此您的事件侦听器永远不会被调用,因为没有任何东西可以调用它。

另一件事是,在像这样的列表项选择情况下,更典型的行为是从ListEvent的currentTarget的selectedItem属性中提取对象(即,你的网格 - 和currentTarget而不是target ,因为event bubbling的工作方式)。在您的情况下,网格的selectedItem属性应该包含一个Employee对象(假设您的网格的dataProvider是Employee对象的ArrayCollection),所以您可以通过这种方式直接引用它:

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}" />

...您将定义一个标记为Bindable的selectedEmployee成员,您可以在DataGrid的itemClick处理程序中设置该成员。这样,您在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 :(得分:1)

您从较低代码示例(DataGrid,我猜)中调用该类中的事件,但该事件在EmployeeForm类中定义,并且事件处理程序同样附加到EmployeeForm实例。据我所知,事件在层次结构中向上传播,而不是向下传播,因此当您从表单的父级触发事件时,它将永远不会触发表单本身的处理程序。从表单触发事件或将事件处理程序附加到父组件。