Question

Je n'ai fait qu'un peu de développement Flex jusqu'à présent, mais j'ai préféré l'approche consistant à créer des contrôles par programme sur des fichiers MXML, car (et s'il te plaît, corrigez-moi si je me trompe !) J'ai compris que vous ne pouvez pas avoir les deux - c'est-à-dire avoir la fonctionnalité de classe dans un fichier de classe ActionScript séparé mais avoir les éléments contenus déclarés dans mxml.

Il ne semble pas y avoir beaucoup de différence en termes de productivité, mais effectuer la liaison de données par programme semble un peu moins que trivial.J'ai jeté un œil à la façon dont le compilateur mxml transforme les expressions de liaison de données.Le résultat est un tas de rappels générés et beaucoup plus de lignes que dans la représentation mxml.Voici donc la question : existe-t-il un moyen d'effectuer une liaison de données par programme qui n'implique pas beaucoup de souffrance ?

Était-ce utile?

La solution

N'ayez pas peur de MXML.C'est idéal pour disposer des vues.Si vous écrivez le vôtre réutilisable Les composants puis les écrire en ActionScript peuvent parfois vous donner un peu plus de contrôle, mais pour les vues non réutilisables, MXML est bien meilleur.C'est plus concis, les fixations sont extrêmement simples à mettre en place, etc.

Cependant, les liaisons en ActionScript pur ne doivent pas nécessairement être très pénibles.Cela ne sera jamais aussi simple que dans MXML où beaucoup de choses sont faites pour vous, mais cela peut être fait sans trop d'effort.

Ce que tu as c'est BindingUtils et ce sont des méthodes bindSetter et bindProperty.J'utilise presque toujours le premier, car je veux généralement travailler ou appeler invalidateProperties lorsque les valeurs changent, je ne souhaite presque jamais simplement définir une propriété.

Ce que vous devez savoir, c'est que ces deux-là renvoient un objet du type ChangeWatcher, si vous souhaitez supprimer la liaison pour une raison quelconque, vous devez conserver cet objet.C'est ce qui rend les liaisons manuelles dans ActionScript un peu moins pratiques que celles dans MXML.

Commençons par un exemple simple :

BindingUtils.bindSetter(nameChanged, selectedEmployee, "name");

Ceci configure une liaison qui appellera la méthode nameChanged quand le name propriété sur l'objet dans la variable selectedEmployee changements.Le nameChanged La méthode recevra la nouvelle valeur du name propriété comme argument, elle devrait donc ressembler à ceci :

private function nameChanged( newName : String ) : void 

Le problème avec cet exemple simple est qu'une fois que vous avez configuré cette liaison, elle se déclenchera à chaque fois que la propriété de l'objet spécifié change.La valeur de la variable selectedEmployee peut changer, mais la liaison est toujours configurée pour l'objet vers lequel la variable pointait auparavant.

Il existe deux manières de résoudre ce problème :soit pour garder le ChangeWatcher renvoyé par BindingUtils.bindSetter autour et appeler unwatch dessus lorsque vous souhaitez supprimer la liaison (puis configurer une nouvelle liaison à la place), ou vous lier à vous-même.Je vais d'abord vous montrer la première option, puis vous expliquer ce que je veux dire par vous lier à vous-même.

Le currentEmployee pourrait être transformé en une paire getter/setter et implémenté comme ceci (montrant uniquement le setter) :

public function set currentEmployee( employee : Employee ) : void {
    if ( _currentEmployee != employee ) {
        if ( _currentEmployee != null ) {
            currentEmployeeNameCW.unwatch();
        }

        _currentEmployee = employee;

        if ( _currentEmployee != null ) {
            currentEmployeeNameCW = BindingUtils.bindSetter(currentEmployeeNameChanged, _currentEmployee, "name");
        }
    }
}

Ce qui se passe, c'est que lorsque le currentEmployee La propriété est définie, il regarde s'il y avait une valeur précédente et, si c'est le cas, supprime la liaison pour cet objet (currentEmployeeNameCW.unwatch()), alors il définit la variable privée, et à moins que la nouvelle valeur ne soit null établit une nouvelle liaison pour le name propriété.Plus important encore, cela sauve le ChangeWatcher renvoyé par l’appel de liaison.

Il s'agit d'un modèle de reliure de base et je pense qu'il fonctionne bien.Il existe cependant une astuce qui peut être utilisée pour rendre les choses un peu plus simples.Vous pouvez plutôt vous lier à vous-même.Au lieu de configurer et de supprimer des liaisons à chaque fois que currentEmployee modifications de propriété, vous pouvez demander au système de liaison de le faire pour vous.Dans ton creationComplete gestionnaire (ou constructeur ou au moins un peu plus tôt), vous pouvez configurer une liaison comme ceci :

BindingUtils.bindSetter(currentEmployeeNameChanged, this, ["currentEmployee", "name"]);

Cela établit une liaison non seulement avec le currentEmployee propriété sur this, mais aussi au name propriété sur cet objet.Donc, à chaque fois, change la méthode currentEmployeeNameChanged sera appelé.Il n'est pas nécessaire de sauvegarder le ChangeWatcher car la liaison ne devra jamais être supprimée.

La deuxième solution fonctionne dans de nombreux cas, mais j'ai trouvé que la première est parfois nécessaire, notamment lorsque l'on travaille avec des liaisons dans des classes non-vues (puisque this doit être un répartiteur d'événements et le currentEmployee doit être lié pour que cela fonctionne).

Autres conseils

Il existe à ce jour.:)

Je viens de publier mon projet de liaison de données ActionScript en open source : http://code.google.com/p/bindage-tools

BindageTools est une alternative à BindingUtils (voir le jeu de mots ici ?) qui utilise une API fluide dans laquelle vous déclarez vos liaisons de données dans un style pipeline :

Bind.fromProperty(person, "firstName")
    .toProperty(firstNameInput, "text");

Liaisons bidirectionnelles :

Bind.twoWay(
    Bind.fromProperty(person, "firstName"),
    Bind.fromProperty(firstNameInput, "text"));

Conversion et validation explicites des données :

Bind.twoWay(
    Bind.fromProperty(person, "age")
        .convert(valueToString()),
    Bind.fromProperty(ageInput, "text")
        .validate(isNumeric()) // (Hamcrest-as3 matcher)
        .convert(toNumber()));

Etc.Il y a beaucoup plus d'exemples sur le site.Il existe également de nombreuses autres fonctionnalités. Venez y jeter un œil.--Matthieu

Modifier:API mises à jour

Une façon de séparer le MXML et l'ActionScript d'un composant dans des fichiers distincts consiste à faire quelque chose de similaire au modèle de code derrière ASP.Net 1.x.Dans ce modèle, la partie déclarative (le MXML dans ce cas) est une sous-classe de la partie impérative (l'ActionScript).Je pourrais donc déclarer le code derrière pour une classe comme ceci :

package CustomComponents
{
    import mx.containers.*;
    import mx.controls.*;
    import flash.events.Event;

    public class MyCanvasCode extends Canvas
    {
        public var myLabel : Label;

        protected function onInitialize(event : Event):void
        {
            MyLabel.text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.";
        }
    }
}

...et le balisage comme ceci :

<?xml version="1.0" encoding="utf-8"?>
<MyCanvasCode xmlns="CustomComponents.*" 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    initialize="onInitialize(event)">
    <mx:Label id="myLabel"/>    
</MyCanvasCode>

Comme vous pouvez le voir sur cet exemple, un inconvénient de cette approche est que vous devez déclarer des contrôles comme monÉtiquette dans les deux fichiers.

il existe un moyen que j'utilise habituellement pour utiliser mxml et action script ensemble :Tous mes composants mxml héritent d'une classe de script d'action où j'ajoute le code le plus complexe.Ensuite, vous pouvez faire référence aux écouteurs d'événements implémentés dans cette classe dans le fichier mxml.

Salutations,

Ruth

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top