Pergunta

Eu só desenvolvi um pouco o Flex até agora, mas preferi a abordagem de criação de controles programaticamente em vez de arquivos mxml, porque (e por favor, corrija-me se eu estiver errado!) Concluí que você não pode ter as duas coisas - ou seja, ter a funcionalidade da classe em um arquivo de classe ActionScript separado, mas ter os elementos contidos declarados em mxml.

Não parece haver muita diferença em termos de produtividade, mas vincular dados programaticamente parece um pouco menos que trivial.Dei uma olhada em como o compilador mxml transforma as expressões de vinculação de dados.O resultado é um monte de retornos de chamada gerados e muito mais linhas do que na representação mxml.Então aqui está a pergunta: existe uma maneira de vincular dados programaticamente que não envolva muitos danos?

Foi útil?

Solução

Não tenha medo do MXML.É ótimo para definir visualizações.Se você escrever o seu próprio reutilizável componentes e, em seguida, escrevê-los em ActionScript pode, às vezes, fornecer um pouco mais de controle, mas para visualizações não reutilizáveis, o MXML é muito melhor.É mais conciso, as ligações são extremamente fáceis de configurar, etc.

No entanto, vinculações em ActionScript puro não precisam ser tão complicadas.Nunca será tão simples como no MXML, onde muitas coisas são feitas para você, mas pode ser feito sem muito esforço.

O que você tem é BindingUtils e são métodos bindSetter e bindProperty.Quase sempre uso o primeiro, pois geralmente quero fazer algum trabalho ou ligar invalidateProperties quando os valores mudam, quase nunca quero apenas definir uma propriedade.

O que você precisa saber é que esses dois retornam um objeto do tipo ChangeWatcher, se quiser remover a ligação por algum motivo, você deverá manter esse objeto.É isso que torna as vinculações manuais no ActionScript um pouco menos convenientes do que as do MXML.

Vamos começar com um exemplo simples:

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

Isso configura uma ligação que chamará o método nameChanged quando o name propriedade no objeto na variável selectedEmployee mudanças.O nameChanged método receberá o novo valor do name propriedade como argumento, então deve ficar assim:

private function nameChanged( newName : String ) : void 

O problema com este exemplo simples é que depois de configurar esta ligação, ela será acionada sempre que a propriedade do objeto especificado for alterada.O valor da variável selectedEmployee pode mudar, mas a ligação ainda está configurada para o objeto para o qual a variável apontou antes.

Existem duas maneiras de resolver isso:seja para manter o ChangeWatcher retornado por BindingUtils.bindSetter por aí e ligue unwatch nele quando quiser remover a ligação (e, em seguida, configurar uma nova ligação) ou vincular a si mesmo.Mostrarei primeiro a primeira opção e depois explicarei o que quero dizer com vinculação a si mesmo.

O currentEmployee poderia ser transformado em um par getter/setter e implementado assim (mostrando apenas o 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");
        }
    }
}

O que acontece é que quando o currentEmployee propriedade está definida, ele verifica se havia um valor anterior e, em caso afirmativo, remove a ligação desse objeto (currentEmployeeNameCW.unwatch()), então ele define a variável privada e, a menos que o novo valor tenha sido null estabelece uma nova vinculação para o name propriedade.O mais importante é que ele salva o ChangeWatcher retornado pela chamada de ligação.

Este é um padrão de ligação básico e acho que funciona bem.Existe, no entanto, um truque que pode ser usado para tornar isso um pouco mais simples.Você pode se vincular a si mesmo.Em vez de configurar e remover vinculações cada vez que o currentEmployee alterações de propriedade, você pode fazer com que o sistema de ligação faça isso por você.Na tua creationComplete manipulador (ou construtor ou pelo menos algum tempo antes), você pode configurar uma ligação assim:

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

Isto estabelece uma ligação não só com o currentEmployee propriedade em this, mas também para o name propriedade neste objeto.Então, a qualquer momento, qualquer um deles muda o método currentEmployeeNameChanged será chamado.Não há necessidade de salvar o ChangeWatcher porque a ligação nunca terá que ser removida.

A segunda solução funciona em muitos casos, mas descobri que a primeira às vezes é necessária, especialmente quando se trabalha com ligações em classes que não são de visualização (já que this tem que ser um despachante de eventos e o currentEmployee tem que ser vinculável para funcionar).

Outras dicas

Existe até hoje.:)

Acabei de lançar meu projeto de vinculação de dados ActionScript como código aberto: http://code.google.com/p/bindage-tools

BindageTools é uma alternativa ao BindingUtils (viu o jogo de palavras aí?) Que usa uma API fluente onde você declara suas ligações de dados em um estilo de pipeline:

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

Ligações bidirecionais:

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

Conversão e validação explícita de dados:

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

Etc.Existem muitos mais exemplos no site.Há muitos outros recursos também - venha dar uma olhada.--Mateus

Editar:APIs atualizadas

Uma maneira de separar o MXML e o ActionScript de um componente em arquivos separados é fazer algo semelhante ao modelo code-behind do ASP.Net 1.x.Neste modelo a parte declarativa (neste caso o MXML) é uma subclasse da parte imperativa (o ActionScript).Então, eu poderia declarar o código por trás de uma classe 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.";
        }
    }
}

... e a marcação assim:

<?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 você pode ver neste exemplo, uma desvantagem dessa abordagem é que você precisa declarar controles como minha etiqueta em ambos os arquivos.

existe uma maneira que costumo usar para usar mxml e script de ação juntos:Todos os meus componentes mxml herdam de uma classe de script de ação onde adiciono o código mais complexo.Em seguida, você pode consultar os ouvintes de eventos implementados nesta classe no arquivo mxml.

Cumprimentos,

Rute

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top