2009-02-13 68 views
0

讓我首先說我對Flex和動作腳本非常陌生。無論如何,我試圖創建一個自定義事件來選擇一個員工並填充表單。事件正在發送(dispatchEvent(event)返回true),但處理程序中設置的斷點永遠不會被命中。在FLEX中調度自定義事件的問題

這裏是我的代碼的某些代碼段(佈置合理,便於更好地理解):

員工表單自定義組件

<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> 

回答

3

有一些事情在這裏引起麻煩。 :)

首先,這個聲明在您的自定義組件:

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

...宣佈對您的自定義組件調度這個特定事件的編譯器,但你實際上包含您的調度它文檔,而不是您的自定義組件 - 所以您的事件偵聽器永遠不會被調用,因爲沒有任何設置可以調用它。

另一件事是,在像這樣的列表項選擇情況下,更典型的行爲是從ListEvent的currentTarget的selectedItem屬性中提取對象(即,您的網格 - 和currentTarget,而不是目標,因爲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}" /> 

...你定義一個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

你調度在較低代碼示例中的類(DataGrid,I gu ess),但事件在EmployeeForm類中定義,並且事件處理程序同樣附加到EmployeeForm實例。據我所知,事件在層次結構中傳播,而不是在層次結構中傳播,所以當你從表單的父對象中引發事件時,事件將永遠不會觸發表單本身的處理程序。從表單中觸發事件或將事件處理程序附加到父組件。