Attenzione Flex: Impossibile collegarsi alla proprietà 'pippo' sulla classe 'Oggetto' (classe non è un IEventDispatcher)
-
06-09-2019 - |
Domanda
Ho un oggetto che contiene una dozzina di campi che voglio legare per formare gli elementi, in modo che possa utilizzare quell'oggetto per inviare i dati al server per essere salvato.
Definizione del mio oggetto contenitore:
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
è assegnato in fase di esecuzione ad un indice specifico da un ArrayCollection, sto solo utilizzando l'oggetto emptyLink
a fini di inizializzazione, per lo più.
<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>
Naturalmente, questo compila e visualizza bene, ma ci sono avvertimenti di runtime per ogni istanza:
Attenzione: incapace di legare alla proprietà 'Trigger1' sulla classe 'Oggetto' (classe non è un IEventDispatcher) Avviso: impossibile associare alla proprietà 'Trigger2' sulla classe 'Oggetto' (classe non è un IEventDispatcher) Avviso: impossibile associare alla proprietà 'Trigger3' sulla classe 'Oggetto' (classe non è un IEventDispatcher) Avviso: impossibile associare alla proprietà 'trigger4' sulla classe 'Oggetto' (classe non è un IEventDispatcher) Avviso: impossibile associare alla proprietà 'trigger5' sulla classe 'Oggetto' (classe non è un IEventDispatcher)
E l'oggetto currentLink
non viene aggiornato quando i campi TextInput
vengono modificati.
La risposta ovvia è che il mio oggetto deve essere un'istanza di una classe che implementa IEventDispatcher
. Quello che la risposta non mi dice è i particolari di attuazione di tale interfaccia, e se c'è un modo più semplice per fare questo (ciò che è necessario cosa non lo è?) - come un costruito in classe che accetta volentieri le mie proprietà personalizzate e consentire per il legame, senza di me doversi preoccupare i particolari che implementa l'interfaccia.
Esiste un tale classe esiste? Se no, qual è il minimo indispensabile e / o standard accettato per realizzare questo compito?
Soluzione
È necessario utilizzare ObjectProxy (come cita Chetan) - ma è anche necessario utilizzare valueCommit per ottenere il testo immesso nell'input di nuovo nella vostra oggetto:
<?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>
Altri suggerimenti
Object
non invia eventi. Anche se avete fatto la variabile Bindable, le proprietà dell'oggetto a cui fa riferimento il currentLink
variabile non può essere vincolato.
Usa ObjectProxy
invece.
[Bindable] public var currentLink:ObjectProxy = new ObjectProxy(emptyLink);
La prima cosa che si vorrà sapere è che il legame di Flex 3 non è bidirezionale. L'espressione vincolante farà in modo che se la fonte dell'espressione di legame (currentLink.trigger1) cambia che la porta (TextInput) riceve la notifica della modifica e aggiornare di conseguenza. Se si desidera che il legame di andare nella direzione opposta, ci sono almeno due modi per farlo:
- Utilizza il mx: Legatura tag per dirigere TextInput.text tornare all'oggetto
- BindingUtils per fare questo a livello di codice, invece.
In Flex 4 si stanno introducendo una nuova sintassi per bidirezionale @ {} some.binding.expression vincolante ma non è disponibile in Flex 3.
Al 2 ° parte: l'errore che si sta ricevendo è perché si sono vincolanti ad un "generico" prototipo oggetto. Quando si applica il [Bindable] tag di metadati a una proprietà o di classe, il compilatore genera mxmlc AS codice che include l'uso di utility di legame e gli osservatori del cambiamento di proprietà per fare rendere il legame accada. Tuttavia non è possibile effettuare il prototipo dell'oggetto fare questo dal momento che è un built-in. È possibile creare una classe ActionScript personalizzato che è associabile (o ha alcune proprietà associabile). Il compilatore mxmlc genererà una classe che implementa IEventDispatcher e sostiene pertanto vincolante. Questo ha il vantaggio di essere più veloce di oggetti prototipo e ti dà in fase di compilazione, vale a dire si riceverà un errore di compilazione, se si fa riferimento a una proprietà non valida anche.
L'altra alternativa è quella di avvolgere il vostro prototipo nel ObjectProxy come uno degli altri SO membri ha suggerito.
Solo un consiglio su come trovare il codice incriminato in un progetto più ampio - mettere un punto di interruzione sulla due
trace("warning: unable to bind to property '"
linee nella classe PropertyWatcher del SDK (Naviga> Open Type> ...). Stacktrace sarà quindi aiuterà a trovare il componente dell'interfaccia utente che contiene il rotto vincolante.
In generale, il motivo per cui si ottiene "in grado di legarsi alla proprietà foo su una classe, è perché o si è manca un getter o setter per foo . potrebbe anche fare foo ambito di una variabile pubblica, (anche se questo si rompe incapsulamento)
Quindi è necessario Entrambi questi per farlo andare via:
public function set foo (o:FooObject) : void {
...
}
o
public function get foo() : FooObject {
...
}
Ecco il LiveDocs riferimento per l'interfaccia. E 'più o meno quello che sarebbe stato ovvio.
Per citare:
In generale, il modo più semplice per una classe definita dall'utente per acquisire funzioni di invio degli eventi è quello di estendere EventDispatcher.
Quindi,
const private static emptyLink: EventDispatcher = {
Non ho usato Flex per molto tempo, e questo potrebbe non soddisfare le vostre esigenze, ma perché non usare XML? Credo che si può impostare il valore di testo TextInput attributi in XML.
sto usando pseudo-codice, ma qualcosa di simile ha senso per me:
[Bindable] private static const currentLink:XML = <root>
<trigger1 value=""/>
<trigger2 value="" />
</root>;
...
<mx:TextInput id="trigger1" width ... text="{currentLink.trigger1.@value}" />
Qualcosa di simile, forse?