Pregunta

Hasta ahora solo he desarrollado un poco en Flex, pero he preferido el enfoque de crear controles mediante programación en lugar de archivos mxml, porque (y por favor, ¡corríjame si me equivoco!) He deducido que no se pueden tener las dos cosas, es decir, tener la funcionalidad de clase en un archivo de clase ActionScript separado pero tener los elementos contenidos declarados en mxml.

No parece haber mucha diferencia en cuanto a productividad, pero vincular datos mediante programación parece algo menos que trivial.Eché un vistazo a cómo el compilador mxml transforma las expresiones de enlace de datos.El resultado es un montón de devoluciones de llamada generadas y muchas más líneas que en la representación mxml.Entonces aquí está la pregunta: ¿Hay alguna manera de vincular datos mediante programación que no implique mucho daño?

¿Fue útil?

Solución

No tengas miedo de MXML.Es genial para diseñar vistas.Si escribes el tuyo reutilizable Los componentes y luego escribirlos en ActionScript a veces pueden brindarle un poco más de control, pero para vistas no reutilizables, MXML es mucho mejor.Es más conciso, los enlaces son extremadamente fáciles de configurar, etc.

Sin embargo, los enlaces en ActionScript puro no tienen por qué ser tan complicados.Nunca será tan sencillo como en MXML, donde se hacen muchas cosas por ti, pero se puede hacer sin demasiado esfuerzo.

lo que tienes es BindingUtils y sus métodos bindSetter y bindProperty.Casi siempre uso el primero, ya que normalmente quiero trabajar o llamar invalidateProperties cuando los valores cambian, casi nunca solo quiero establecer una propiedad.

Lo que necesitas saber es que estos dos devuelven un objeto del tipo ChangeWatcher, si desea eliminar el enlace por algún motivo, debe conservar este objeto.Esto es lo que hace que los enlaces manuales en ActionScript sean un poco menos convenientes que los de MXML.

Comencemos con un ejemplo simple:

BindingUtils.bindSetter(nameChanged, selectedEmployee, "name");

Esto configura un enlace que llamará al método. nameChanged cuando el name propiedad sobre el objeto en la variable selectedEmployee cambios.El nameChanged El método recibirá el nuevo valor del name propiedad como argumento, por lo que debería verse así:

private function nameChanged( newName : String ) : void 

El problema con este ejemplo simple es que una vez que haya configurado este enlace, se activará cada vez que cambie la propiedad del objeto especificado.El valor de la variable. selectedEmployee puede cambiar, pero el enlace aún está configurado para el objeto al que apuntaba la variable antes.

Hay dos formas de solucionar esto:ya sea para mantener el ChangeWatcher devuelto por BindingUtils.bindSetter alrededor y llamar unwatch en él cuando desee eliminar el enlace (y luego configurar un nuevo enlace), o vincularse a usted mismo.Primero le mostraré la primera opción y luego le explicaré lo que quiero decir con vincularse a usted mismo.

El currentEmployee podría convertirse en un par getter/setter e implementarse de esta manera (solo mostrando el setter):

public function set currentEmployee( employee : Employee ) : void {
    if ( _currentEmployee != employee ) {
        if ( _currentEmployee != null ) {
            currentEmployeeNameCW.unwatch();
        }

        _currentEmployee = employee;

        if ( _currentEmployee != null ) {
            currentEmployeeNameCW = BindingUtils.bindSetter(currentEmployeeNameChanged, _currentEmployee, "name");
        }
    }
}

Lo que pasa es que cuando el currentEmployee Cuando la propiedad está configurada, busca ver si había un valor anterior y, de ser así, elimina el enlace para ese objeto (currentEmployeeNameCW.unwatch()), luego establece la variable privada y, a menos que el nuevo valor fuera null establece una nueva vinculación para el name propiedad.Lo más importante es que salva la ChangeWatcher devuelto por la llamada vinculante.

Este es un patrón de encuadernación básico y creo que funciona bien.Sin embargo, existe un truco que puede utilizarse para hacerlo un poco más sencillo.En su lugar, puedes unirte a ti mismo.En lugar de colocar y quitar fijaciones cada vez que el currentEmployee cambios de propiedad, puede hacer que el sistema vinculante lo haga por usted.En tus creationComplete controlador (o constructor o al menos algún tiempo antes) puede configurar un enlace de esta manera:

BindingUtils.bindSetter(currentEmployeeNameChanged, this, ["currentEmployee", "name"]);

Esto establece una vinculación no sólo para el currentEmployee propiedad en this, sino también a la name propiedad sobre este objeto.Entonces, en cualquier momento, cambia el método. currentEmployeeNameChanged sera llamado.No es necesario guardar el ChangeWatcher porque nunca será necesario quitar la encuadernación.

La segunda solución funciona en muchos casos, pero descubrí que la primera a veces es necesaria, especialmente cuando se trabaja con enlaces en clases sin vista (ya que this tiene que ser un despachador de eventos y el currentEmployee tiene que ser vinculable para que funcione).

Otros consejos

Existe a partir de hoy.:)

Acabo de publicar mi proyecto de enlace de datos ActionScript como código abierto: http://code.google.com/p/bindage-tools

BindageTools es una alternativa a BindingUtils (¿ves el juego de palabras allí?) que utiliza una API fluida donde declaras tus enlaces de datos en un estilo de canalización:

Bind.fromProperty(person, "firstName")
    .toProperty(firstNameInput, "text");

Enlaces bidireccionales:

Bind.twoWay(
    Bind.fromProperty(person, "firstName"),
    Bind.fromProperty(firstNameInput, "text"));

Conversión y validación de datos explícita:

Bind.twoWay(
    Bind.fromProperty(person, "age")
        .convert(valueToString()),
    Bind.fromProperty(ageInput, "text")
        .validate(isNumeric()) // (Hamcrest-as3 matcher)
        .convert(toNumber()));

Etc.Hay muchos más ejemplos en el sitio.También hay muchas otras características: échale un vistazo.--Mateo

Editar:API actualizadas

Una forma de separar MXML y ActionScript de un componente en archivos separados es hacer algo similar al modelo de código subyacente de ASP.Net 1.x.En este modelo, la parte declarativa (el MXML en este caso) es una subclase de la parte imperativa (el ActionScript).Entonces podría declarar el código subyacente para una clase como esta:

package CustomComponents
{
    import mx.containers.*;
    import mx.controls.*;
    import flash.events.Event;

    public class MyCanvasCode extends Canvas
    {
        public var myLabel : Label;

        protected function onInitialize(event : Event):void
        {
            MyLabel.text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.";
        }
    }
}

...y el marcado así:

<?xml version="1.0" encoding="utf-8"?>
<MyCanvasCode xmlns="CustomComponents.*" 
    xmlns:mx="http://www.adobe.com/2006/mxml"
    initialize="onInitialize(event)">
    <mx:Label id="myLabel"/>    
</MyCanvasCode>

Como puede ver en este ejemplo, una desventaja de este enfoque es que debe declarar controles como miEtiqueta en ambos archivos.

Hay una forma que suelo utilizar para utilizar mxml y action script juntos:Todos mis componentes mxml heredan de una clase de script de acción donde agrego el código más complejo.Luego puede consultar los detectores de eventos implementados en esta clase en el archivo mxml.

Saludos,

Piedad

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