Advertencia Flex: No se puede enlazar a la propiedad 'foo' de la clase 'Objeto' (clase no es una IEventDispatcher)

StackOverflow https://stackoverflow.com/questions/928081

Pregunta

Tengo un objeto que contiene una docena de campos que quiero unir para formar elementos, de modo que pueda utilizar ese objeto para enviar los datos de vuelta al servidor para ser salvo.

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, sólo estoy usando el objeto emptyLink con fines 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 en tiempo de ejecución para cada instancia:

  

Advertencia: incapaz de unirse a la propiedad 'trigger1' de la clase 'Objeto' (clase no es una IEventDispatcher)   advertencia: no se puede obligar a la propiedad 'trigger2' de la clase 'Objeto' (clase no es una IEventDispatcher)   advertencia: no se puede obligar a la propiedad 'Trigger3' de la clase 'Objeto' (clase no es una IEventDispatcher)   advertencia: no se puede obligar a la propiedad 'trigger4' de la clase 'Objeto' (clase no es una IEventDispatcher)   advertencia: no se puede obligar a la propiedad 'trigger5' de la clase 'Objeto' (clase no es una IEventDispatcher)

Y el objeto currentLink no se actualiza cuando se cambian los campos TextInput.

La respuesta obvia es que mi objeto necesita ser una instancia de una clase que implementa IEventDispatcher. Lo que esa respuesta no me dice es los detalles de la implementación de dicha interfaz, y si hay una manera más sencilla de hacer esto (lo que se requiere lo que es no?) - como un sistema incorporado en la clase que aceptará de buen grado mis propiedades personalizadas y permitir para la unión, sin tener que preocuparse por los detalles de la implementación de la interfaz.

¿Existe una clase de este tipo? Si no es así, ¿cuál es el mínimo y / o estándar aceptado para realizar esta tarea?

¿Fue útil?

Solución

Es necesario utilizar ObjectProxy (como se menciona Chetan) - pero también es necesario para utilizar valueCommit para obtener el texto que introduzca en la entrada de nuevo 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>

Otros consejos

Object no distribuye eventos. A pesar de haber hecho la variable enlazables, las propiedades del objeto referenciado por el currentLink variable no puede obligarse.

Uso ObjectProxy lugar.

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

La primera cosa que usted quiere saber es que la unión en Flex 3 no es bidireccional. La expresión de enlace se asegurará de que si el origen de la expresión de unión (currentLink.trigger1) cambia que el objetivo (TextInput) recibirá una notificación del cambio y actualizar en consecuencia. Si desea que la unión de ir en la otra dirección, hay por lo menos dos maneras de hacer esto:

  1. Utilice la mx: Encuadernación etiqueta para dirigir TextInput.text de nuevo al objeto
  2. Use BindingUtils hacer esto mediante programación en su lugar.

En Flex 4 que están introduciendo una nueva sintaxis para bidireccional @ {} some.binding.expression vinculante, pero que no está disponible en Flex 3.

En la segunda parte: el error que está recibiendo es porque va a enlazar a un prototipo de objeto "genérico". Cuando se aplica el [Bindable] etiqueta de metadatos a una propiedad o clase, el compilador genera mxmlc AS código que incluye el uso de los servicios de enlace y observadores de cambio de propiedad de hacer crea la unión suceda. Sin embargo no se puede hacer que el objeto prototipo de hacer esto ya que es un built-in. Se puede crear una clase de ActionScript a medida que es capaz de unirse (o tiene ciertas propiedades enlazable). El compilador mxmlc generará una clase que implementa IEventDispatcher por lo que apoya la unión. Esto tiene la ventaja de ser más rápido que los objetos prototipo y también le da tiempo de compilación de cheques, es decir, usted recibirá un error de compilación si hace referencia a una propiedad no válida.

La otra alternativa consiste en envolver su prototipo en ObjectProxy como uno de los otros miembros de la SO ha sugeridas.

Sólo un consejo sobre cómo averiguar el código erróneo en un proyecto más amplio - 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> Open Type> ...). StackTrace a continuación le ayudará a encontrar el componente de interfaz de usuario que sujeta la unión rota.

En general, la razón por la que se obtiene "incapaz de unirse a foo propiedad de una clase, es porque está bien echa en falta un captador o colocador de foo . Usted podría también hacer foo ámbito para una variable pública, (aunque esto rompe la encapsulación)

Así que hay dos de estos para hacer que desaparezca:

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

o

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

He aquí hacen referencia a los LiveDocs para la interfaz. Es más o menos lo que sería obvia.

Para la cita:

  

En general, la manera más fácil para una clase definida por el usuario para obtener capacidades de despacho de eventos es extender EventDispatcher.

Por lo tanto,

  

static const privada emptyLink: EventDispatcher = {

No he estado usando Flex por mucho tiempo, y esto podría no ajustarse a sus requerimientos, pero ¿por qué no uso de XML? Creo que se puede establecer el valor de texto TextInput a 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?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top