Advertencia de Flex: no se puede vincular a la propiedad ''foo'' en la clase ''Objeto''(la clase no es un IEventDispatcher)
actionscript-3 binding (7)
Tengo un objeto que contiene aproximadamente una docena de campos que quiero vincular para formar elementos, de modo que pueda usar ese objeto para enviar los datos de vuelta al servidor que se va a guardar.
Definición de mi objeto contenedor:
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
se asigna en tiempo de ejecución a un índice específico de un ArrayCollection, solo estoy usando el objeto emptyLink
para propósitos de inicialización, en su mayoría.
<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>
Por supuesto, esto compila y muestra muy bien, pero hay advertencias de tiempo de ejecución para cada instancia:
advertencia: no se puede vincular a la propiedad ''trigger1'' en la clase ''Objeto'' (clase no es un IEventDispatcher) advertencia: no se puede enlazar a la propiedad ''trigger2'' en la clase ''Objeto'' (clase no es un IEventDispatcher) advertencia: no se puede enlazar a propiedad ''trigger3'' en clase ''Objeto'' (clase no es un IEventDispatcher) advertencia: no se puede enlazar a la propiedad ''trigger4'' en clase ''Objeto'' (clase no es un IEventDispatcher) advertencia: no se puede enlazar a la propiedad ''trigger5'' en clase ''Objeto'' (la clase no es un IEventDispatcher)
Y el objeto currentLink
no se actualiza cuando los campos TextInput
se cambian.
La respuesta obvia es que mi objeto debe ser una instancia de una clase que implemente IEventDispatcher
. Lo que esa respuesta no me dice son los detalles de la implementación de esa interfaz (¿qué se requiere? ¿Qué no?), Y si hay una manera más simple de hacer esto, como una clase incorporada que gustosamente acepte mis propiedades personalizadas y permita para el enlace, sin que tenga que preocuparse por los detalles de la implementación de la interfaz.
¿Existe tal clase? Si no, ¿cuál es el estándar mínimo y / o aceptado para realizar esta tarea?
En general, la razón por la que "no se puede enlazar con la propiedad foo en una clase, es porque le falta un getter o setter para foo . También puede hacer que foo alcance una variable pública, (aunque esto rompe la encapsulación)
Entonces necesita Ambos para hacer que desaparezca:
public function set foo (o:FooObject) : void {
...
}
o
public function get foo() : FooObject {
...
}
Lo primero que querrá saber es que el enlace en Flex 3 no es bidireccional. La expresión de enlace asegurará que si la fuente de la expresión de enlace (currentLink.trigger1) cambia, el objetivo (TextInput) recibirá la notificación del cambio y la actualización en consecuencia. Si desea que el enlace vaya en la otra dirección, hay al menos dos formas de hacerlo:
- Utilice la etiqueta mx: Binding para dirigir TextInput.text de regreso al objeto
- Use BindingUtils para hacer esto programáticamente en su lugar.
En Flex 4 están introduciendo una nueva sintaxis para el enlace bidireccional @ {some.binding.expression} pero no está disponible en Flex 3.
En la segunda parte: el error que está recibiendo es porque está vinculando a un objeto prototipo "genérico". Cuando aplica la etiqueta de metadatos [Bindable] a una propiedad o clase, el compilador MXMLC genera código AS que incluye el uso de utilidades de enlace y vigilantes de cambio de propiedad para hacer que la vinculación suceda. Sin embargo, no puede hacer que el Objeto prototipo lo haga ya que está incorporado. Puede crear una clase de ActionScript personalizada que sea vinculable (o tenga ciertas propiedades enlazables). El compilador MXMLC generará una clase que implementa IEventDispatcher y, por lo tanto, admite el enlace. Esto tiene la ventaja de ser más rápido que los objetos prototipo y también le proporciona una verificación en tiempo de compilación, es decir, recibirá un error de compilación si hace referencia a una propiedad no válida.
La otra alternativa es envolver su prototipo en ObjectProxy como lo sugirió uno de los otros miembros de SO.
Necesita usar ObjectProxy (como lo menciona Chetan), pero también necesita usar valueCommit para obtener el texto que ingresa en la entrada BACK en su objeto:
<?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>
No he usado Flex por mucho tiempo, y puede que esto no se ajuste a sus requisitos, pero ¿por qué no usar XML? Creo que puede establecer el valor de texto de TextInput para los atributos en el XML.
Estoy usando pseudo-código, pero algo como esto tiene sentido para mí:
[Bindable] private static const currentLink:XML = <root>
<trigger1 value=""/>
<trigger2 value="" />
</root>;
...
<mx:TextInput id="trigger1" width ... text="{currentLink.trigger1.@value}" />
Algo como esto, tal vez?
Solo un consejo sobre cómo descubrir el código ofensivo en un proyecto más grande: poner un punto de interrupción en los dos
trace("warning: unable to bind to property ''"
líneas en la clase PropertyWatcher del SDK (Navegar> Tipo abierto> ...). Stacktrace lo ayudará a encontrar el componente ui que contiene el enlace roto.
Aquí está la referencia de Livedocs para la interfaz. Es más o menos lo que sería obvio.
Citar:
En general, la forma más fácil para una clase definida por el usuario para obtener capacidades de envío de eventos es extender EventDispatcher.
Por lo tanto,
Const privado estático emptyLink: EventDispatcher = {
Object
no despacha eventos. Aunque ha creado la variable Vinculable, las propiedades del objeto al que hace referencia la variable currentLink
no pueden vincularse.
Use ObjectProxy
en ObjectProxy
lugar.
[Bindable] public var currentLink:ObjectProxy = new ObjectProxy(emptyLink);