2009-02-13 11 views
0

Permettez-moi de commencer en disant que je suis assez nouveau pour les scripts flex et action. De toute façon, j'essaie de créer un événement personnalisé pour prendre un employé sélectionné et remplir un formulaire. L'événement est distribué (le dispatchEvent (event) renvoie true) mais les points d'arrêt définis à l'intérieur du gestionnaire ne sont jamais touchés.Problème avec l'envoi d'un événement personnalisé dans FLEX

Voici quelques extraits de mon code (Logiquement pris des dispositions pour une meilleure compréhension):

formulaire employé composant personnalisé

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

Application

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

Répondre

3

Il y a quelques choses qui conspirent pour causer des ennuis ici. :)

Tout d'abord, cette déclaration dans votre composant personnalisé:

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

... annonce au compilateur que votre composant personnalisé envoie cet événement particulier, mais vous dispatching réellement avec votre contenant document, plutôt que votre composant personnalisé - de sorte que votre écouteur d'événement ne soit jamais appelé, car il n'y a rien de configuré pour l'appeler. Une autre chose est que, dans des situations de sélection d'éléments de liste comme celle-ci, le comportement le plus courant consiste à extraire l'objet de la propriété selectedItem du currentTarget de ListEvent (ie, votre grille - et currentTarget plutôt que cible, à cause de la façon dont fonctionne event bubbling). Dans votre cas, la propriété SelectedItem de la grille doit contenir un objet employé (en supposant dataProvider votre grille est un ArrayCollection d'objets employés), donc vous devriez faire référence ainsi directement:

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

Utilisation du itemRenderer comme La source de données est en quelque sorte notoirement peu fiable, puisque les rendus d'éléments sont des éléments visuels qui sont réutilisés par le framework d'une manière que vous ne pouvez pas toujours prédire. Il est beaucoup plus sûr, à la place, d'extraire directement l'élément de l'événement comme je l'ai démontré ci-dessus - auquel cas vous n'auriez pas du tout besoin d'un objet "employeeData", puisque vous avez déjà l'objet Employee. Peut-être, cependant, il vaudrait peut-être mieux suggérer une approche plus en phase avec le fonctionnement du framework - une approche dans laquelle aucun envoi d'événement n'est nécessaire en raison des fonctionnalités de liaison de données que vous obtenez. -box avec le cadre. Par exemple, dans votre contenant document:

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

... vous feriez définir un élément de selectedEmployee, marqué comme Bindable, que vous définissez dans le gestionnaire itemClick du DataGrid. De cette façon, l'expression de liaison que vous avez spécifiée sur EmployeeForm s'assurera que le formulaire a toujours une référence à l'employé sélectionné.Puis, sous la forme elle-même:

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

... vous acceptez simplement l'employé sélectionné (qui est marqué bindable à nouveau, pour que les champs de formulaire ont toujours les plus récentes informations sur cet employé choisi).

Est-ce que cela a du sens? Je pourrais simplifier à l'extrême étant donné que je ne connais pas les exigences de votre demande, mais c'est un scénario si courant que je me suis dit que je proposerais une solution à titre d'exemple, pour mieux comprendre la façon conventionnelle de le manipuler. Si, pour une raison quelconque, vous devez envoyer un événement personnalisé, en plus de simplement définir l'élément sélectionné - par exemple, si d'autres composants écoutent cet événement - l'appel dispatchEvent que vous avez spécifié devrait être bien, aussi longtemps que vous comprenez qu'il est le document contenant qui est l'envoi de l'événement, afin que toute personne qui souhaite être informé de celui-ci aurait besoin d'attacher un auditeur spécifique à ce document:

yourContainingDoc.addEventListener("selectEmployeeEvent", yourOtherComponentsSelectionHandler); 

Hope it helps - sensation libre de poster des commentaires et je vais garder un œil sur.

1

Vous dispatching l'événement de la classe dans l'exemple de code inférieur (DataGrid, I gu ess), mais l'événement est défini dans la classe EmployeeForm et le gestionnaire d'événements est également attaché à l'instance EmployeeForm. Au meilleur de ma connaissance, les événements se propagent dans la hiérarchie, pas vers le bas, donc lorsque vous déclenchez l'événement à partir du parent du formulaire, il ne déclenchera jamais les gestionnaires dans le formulaire lui-même. Sortez l'événement du formulaire ou attachez le gestionnaire d'événements au composant parent.

Questions connexes