2008-09-15 10 views
1

Dans Flex, j'ai un document XML tel que:XML Edition dans Flex à l'aide e4x

var xml:XML = <root><node>value1</node><node>value2</node><node>value3</node></root> 

Lors de l'exécution, je veux créer un contrôle TextInput pour chaque noeud sous la racine, et ont les valeurs liés aux valeurs dans le XML. Pour autant que je peux dire que je ne peux pas utiliser BindingUtils pour se lier à e4x noeuds lors de l'exécution (s'il vous plaît me dire si je me trompe!), Donc je suis en train de le faire à la main:

for each (var node:XML in xml.node) 
{ 
    var textInput:TextInput = new TextInput(); 
    var handler:Function = function(event:Event):void 
    { 
     node.setChildren(event.target.text); 
    }; 
    textInput.text = node.text(); 
    textInput.addEventListener(Event.CHANGE, handler); 
    this.addChild(pileHeightEditor); 
} 

Mon problème est que lorsque l'utilisateur édite l'une des TextInputs, le nœud assigné est toujours le dernier rencontré dans la boucle for. Je suis habitué à ce modèle de C#, où chaque fois qu'une fonction anonyme est créée, un "instantané" des valeurs des valeurs utilisées est pris, ainsi "node" serait différent dans chaque fonction de gestionnaire.

Comment puis-je "prendre un instantané" de la valeur actuelle du noeud à utiliser dans le gestionnaire? Ou devrais-je utiliser un modèle différent dans Flex?

Répondre

2

La fermeture capture uniquement une référence à la variable, et non sa valeur actuelle. Étant donné que les variables locales ont une portée de fonction (et non une portée de bloc), chaque itération à travers la boucle crée une fermeture qui capture une référence à la même variable.

Vous pouvez extraire le code de création TextInput dans une fonction distincte, ce qui vous donne une instance de variable distincte à capturer pour la fermeture. Quelque chose comme ceci:

for each (var node:XML in xml.node) 
{ 
    var textInput:TextInput = createTextInput(node); 
    this.addChild(pileHeightEditor); 
} 
... 

private function createTextInput(node:XML) : TextInput { 
    var textInput:TextInput = new TextInput(); 
    var handler:Function = function(event:Event):void 
    { 
     node.setChildren(event.target.text); 
    }; 
    textInput.text = node.text(); 
    textInput.addEventListener(Event.CHANGE, handler); 
    return textInput; 
} 
2

Malheureusement, les fermetures de fonction fonctionnent bizarrement/mal dans Actionscript. Les variables n'obtiennent un "instantané" que lorsqu'elles sont hors de portée. Malheureusement, les variables ont une portée de fonction et ne sont pas bloquées. Cela ne finit donc pas comme vous le voulez.

Vous pouvez créer un dictionnaire à mapper à partir du noeud TextInput ->, ou vous pouvez stocker le noeud dans la propriété data de TextInput. Je souhaite que ce que vous avez décrit fonctionne correctement car c'est un moyen facile/puissant d'exprimer cela.

Questions connexes