2009-05-29 15 views
22

J'ai un objet qui contient une douzaine de champs que je veux lier à des éléments de formulaire, de sorte que je peut utiliser cet objet pour renvoyer les données au serveur à enregistrer.Flex Avertissement: impossible de lier la propriété 'foo' sur la classe 'Object' (la classe n'est pas un IEventDispatcher)

Définition de mon objet conteneur:

private static const emptyLink:Object = { 
    id: -1, title:'', 
    trigger1:'',trigger2:'',trigger3:'',trigger4:'',trigger5:'', 
    linkTitle:'', linkBody:'', 
    answer1:'',answer2:'',answer3:'',answer4:'',answer5:'' 
}; 

[Bindable] public var currentLink:Object = emptyLink; 

currentLink est affecté à l'exécution d'un index spécifique d'un ArrayCollection, je suis juste en utilisant l'objet emptyLink à des fins d'initialisation, la plupart du temps.

<mx:Panel id="triggerPanel" title="Trigger" width="33%"> 
    <mx:VBox id="tpBoxes" width="100%" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5"> 
     <mx:TextInput id="trigger1" width="100%" textAlign="left" text="{currentLink.trigger1}" /> 
     <mx:TextInput id="trigger2" width="100%" textAlign="left" text="{currentLink.trigger2}" /> 
     <mx:TextInput id="trigger3" width="100%" textAlign="left" text="{currentLink.trigger3}" /> 
     <mx:TextInput id="trigger4" width="100%" textAlign="left" text="{currentLink.trigger4}" /> 
     <mx:TextInput id="trigger5" width="100%" textAlign="left" text="{currentLink.trigger5}" /> 
    </mx:VBox> 
</mx:Panel> 

Bien sûr, cela compile et affiche très bien, mais il y a des avertissements d'exécution pour chaque instance:

avertissement: incapable de se lier à la propriété « trigger1 » la classe « Object » (classe pas un IEventDispatcher) avertissement: impossible de lier à la propriété 'trigger2' sur la classe 'Object' (la classe n'est pas un IEventDispatcher) avertissement: impossible de lier à la propriété 'trigger3' sur la classe 'Object' (la classe n'est pas un IEventDispatcher) avertissement: impossible de lier à la propriété 'trigger4' sur la classe 'Object' (la classe n'est pas un IEventDispatcher) avertissement: incapable de se lier à la propriété « trigger5 » sur l'objet de «classe (classe est pas un IEventDispatcher)

Et l'objet currentLink est pas mis à jour lorsque les champs TextInput sont modifiés.

La réponse évidente est que mon objet doit être une instance d'une classe qui implémente IEventDispatcher. Ce que cette réponse ne me dit pas, c'est les détails de l'implémentation de cette interface (qu'est-ce qui est nécessaire, qu'est ce qui ne l'est pas?), Et s'il y a un moyen plus simple de le faire. pour la liaison, sans que je doive m'inquiéter des détails de l'implémentation de l'interface.

Une telle classe existe-t-elle? Si non, quel est le strict minimum et/ou la norme acceptée pour accomplir cette tâche?

Répondre

15

Vous devez utiliser ObjectProxy (comme Chetan mentionne) - mais vous devez également utiliser valueCommit pour obtenir le texte que vous entrez dans l'entrée arrière dans votre objet:

<?xml version="1.0" encoding="utf-8"?> 
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> 
    <mx:Script> 
     <![CDATA[ 
      import mx.utils.ObjectProxy; 
       private static const emptyLink:Object = { 
    id: -1, title:'', 
    trigger1:'',trigger2:'',trigger3:'',trigger4:'',trigger5:'', 
    linkTitle:'', linkBody:'', 
    answer1:'',answer2:'',answer3:'',answer4:'',answer5:'' 
}; 

[Bindable] public var currentLink:ObjectProxy = new ObjectProxy(emptyLink); 


private function handleClick():void 
{ 
    trace(currentLink.trigger1); 
} 
]]> 
</mx:Script> 

<mx:Panel id="triggerPanel" title="Trigger" width="33%"> 
     <mx:VBox id="tpBoxes" width="100%" paddingBottom="5" paddingLeft="5" paddingRight="5" paddingTop="5"> 
       <mx:TextInput id="trigger1" width="100%" textAlign="left" text="{currentLink.trigger1}" valueCommit="{currentLink.trigger1 = trigger1.text;}"/> 

       <mx:Button label="Click" click="handleClick()"/> 
     </mx:VBox> 
</mx:Panel>   

</mx:WindowedApplication> 
0

Je n'utilise pas Flex depuis très longtemps, et cela ne correspond peut-être pas à vos exigences, mais pourquoi ne pas utiliser XML? Je crois que vous pouvez définir la valeur de texte TextInput aux attributs dans le XML.

J'utilise pseudo-code, mais quelque chose comme cela a du sens pour moi:

[Bindable] private static const currentLink:XML = <root> 
                <trigger1 value=""/> 
                <trigger2 value="" /> 
                </root>; 
... 
<mx:TextInput id="trigger1" width ... text="{[email protected]}" /> 

Quelque chose comme ça, peut-être?

8

Object ne distribue pas les événements. Bien que vous ayez créé la variable Bindable, les propriétés de l'objet référencé par la variable currentLink ne peuvent pas être liées.

Utilisez plutôt ObjectProxy.

[Bindable] public var currentLink:ObjectProxy = new ObjectProxy(emptyLink); 
1

Here's the livedocs reference pour l'interface. C'est à peu près ce qui serait évident.

Pour citer:

En général, la meilleure façon pour une classe définie par l'utilisateur pour obtenir des fonctions de distribution est d'étendre EventDispatcher.

Par conséquent,

const private static emptyLink: EventDispatcher = {

+0

votre lien ne va pas à la page dans les livesocs que vous pensiez faire. Chaque page de référence de livesocs a un «lien actuel: ...» dans son pied de page, avec l'URL pour relier directement la page que vous consultez. Utiliser ça. :) –

4

La première chose que vous voulez savoir est que la liaison dans Flex 3 n'est pas bidirectionnel. L'expression de liaison fera en sorte que si la source de l'expression de liaison (currentLink.trigger1) change, la cible (TextInput) recevra une notification de la modification et se mettra à jour en conséquence. Si vous voulez la liaison aller dans l'autre sens, il y a au moins deux façons de le faire:

  1. Utilisez la balise mx: Binding pour diriger TextInput.text à l'objet
  2. Utilisez BindingUtils faire ceci par programme à la place.

Dans Flex 4, ils introduisent une nouvelle syntaxe pour la liaison bidirectionnelle @ {} some.binding.expression mais ce n'est pas disponible dans Flex 3.

Sur la 2ème partie: l'erreur que vous recevez est parce que vous êtes lié à un prototype "générique" Object. Lorsque vous appliquez la balise de métadonnées [Bindable] à une propriété ou à une classe, le compilateur MXMLC génère un code AS qui inclut l'utilisation d'utilitaires de liaison et d'observateurs de changement de propriété pour que la liaison se produise. Cependant, vous ne pouvez pas faire en sorte que l'objet prototype le fasse car il s'agit d'un built-in. Vous pouvez créer une classe ActionScript personnalisée qui peut être liée (ou dont certaines propriétés peuvent être liées). Le compilateur MXMLC génère une classe qui implémente IEventDispatcher et prend donc en charge la liaison. Cela a l'avantage d'être plus rapide que les objets prototypes et vous donne aussi une vérification à la compilation, c'est-à-dire que vous recevrez une erreur de compilation si vous faites référence à une propriété invalide.

L'autre alternative consiste à envelopper votre prototype dans ObjectProxy comme l'a suggéré l'un des autres membres SO.

+0

Si je pouvais accepter 2 réponses, celui-ci serait # 2. J'ai choisi Gabriel parce que c'était la solution la plus simple pour faire ce que je voulais faire. Merci pour toutes les informations, cependant! –

1

En général, la raison pour laquelle vous get "incapable de lier à la propriété foo sur une classe, est parce que vous manque un getter ou un setter pour foo.Vous pouvez également foo scope à une variable publique, (bien que cela casse l'encapsulation)

Vous avez donc besoin Ces deux pour le faire disparaître:

public function set foo (o:FooObject) : void { 
... 
} 

ou

public function get foo() : FooObject { 
... 
} 
2

Juste un conseil sur la façon de trouver le code incriminé dans un plus grand projet - mettre un point d'arrêt sur les deux

trace("warning: unable to bind to property '" 

lignes de la classe PropertyWatcher du SDK (Naviguer> Ouvrir le type> ...). Stacktrace vous aidera alors à trouver le composant ui qui contient la liaison cassée.