0

首先让我说我对 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>
4

2 回答 2

3

这里有几件事合谋造成麻烦。:)

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

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

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

另一件事是,在这样的列表项选择情况下,更典型的行为是从 ListEvent 的 currentTarget 的 selectedItem 属性中提取对象(即,您的网格 - 和 currentTarget 而不是目标,因为事件冒泡的工作方式)。在您的情况下,网格的 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}" />

...您将定义一个 selectedEmployee 成员,标记为 Bindable,您在 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);

希望它有所帮助 - 随时发表评论,我会留意。

于 2009-02-13T13:01:28.547 回答
1

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

于 2009-02-13T09:48:39.930 回答