Frage

Ich habe bisher nur ein wenig an der Flex-Entwicklung gearbeitet, aber ich habe den Ansatz, Steuerelemente programmgesteuert zu erstellen, gegenüber MXML-Dateien vorgezogen, weil (und Bitte, korrigieren Sie mich, wenn ich falsch liege!) Ich habe festgestellt, dass Sie nicht beide Möglichkeiten haben können – das heißt, die Klassenfunktionalität in einer separaten ActionScript-Klassendatei haben, aber die enthaltenen Elemente in mxml deklarieren lassen.

Hinsichtlich der Produktivität scheint es keinen großen Unterschied zu geben, aber die programmgesteuerte Datenbindung scheint alles andere als trivial zu sein.Ich habe mir angeschaut, wie der MXML-Compiler die Datenbindungsausdrücke transformiert.Das Ergebnis ist eine Menge generierter Rückrufe und viel mehr Zeilen als in der MXML-Darstellung.Hier ist also die Frage: Gibt es eine Möglichkeit, die Datenbindung programmgesteuert durchzuführen, ohne dass dabei jede Menge Ärger entsteht?

War es hilfreich?

Lösung

Haben Sie keine Angst vor MXML.Es eignet sich hervorragend zum Anordnen von Ansichten.Wenn Sie Ihre eigenen schreiben wiederverwendbar Komponenten zu erstellen und sie dann in ActionScript zu schreiben, gibt Ihnen manchmal etwas mehr Kontrolle, aber für nicht wiederverwendbare Ansichten ist MXML viel besser.Es ist prägnanter, Bindungen lassen sich extrem einfach einrichten usw.

Bindungen in reinem ActionScript müssen jedoch nicht so mühsam sein.Es wird nie so einfach sein wie in MXML, wo viele Dinge für Sie erledigt werden, aber es kann mit nicht allzu großem Aufwand erledigt werden.

Was Sie haben, ist BindingUtils und es sind Methoden bindSetter Und bindProperty.Ich verwende fast immer Ersteres, da ich normalerweise etwas arbeiten oder anrufen möchte invalidateProperties Wenn sich Werte ändern, möchte ich fast nie einfach nur eine Eigenschaft festlegen.

Sie müssen wissen, dass diese beiden ein Objekt dieses Typs zurückgeben ChangeWatcher, Wenn Sie aus irgendeinem Grund die Bindung entfernen möchten, müssen Sie dieses Objekt festhalten.Aus diesem Grund sind manuelle Bindungen in ActionScript etwas weniger praktisch als in MXML.

Beginnen wir mit einem einfachen Beispiel:

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

Dadurch wird eine Bindung eingerichtet, die die Methode aufruft nameChanged wenn das name Eigenschaft für das Objekt in der Variablen selectedEmployee Änderungen.Der nameChanged Die Methode erhält den neuen Wert von name Eigenschaft als Argument, daher sollte es so aussehen:

private function nameChanged( newName : String ) : void 

Das Problem bei diesem einfachen Beispiel besteht darin, dass diese Bindung nach dem Einrichten jedes Mal ausgelöst wird, wenn sich die Eigenschaft des angegebenen Objekts ändert.Der Wert der Variablen selectedEmployee kann sich ändern, aber die Bindung ist weiterhin für das Objekt eingerichtet, auf das die Variable zuvor gezeigt hat.

Es gibt zwei Möglichkeiten, dieses Problem zu lösen:entweder um das zu behalten ChangeWatcher zurückgegeben von BindingUtils.bindSetter herumlaufen und anrufen unwatch darauf, wenn Sie die Bindung entfernen (und dann stattdessen eine neue Bindung einrichten) oder sich selbst binden möchten.Ich zeige Ihnen zunächst die erste Option und erkläre dann, was ich unter „an sich selbst binden“ verstehe.

Der currentEmployee könnte in ein Getter/Setter-Paar umgewandelt und wie folgt implementiert werden (zeigt nur den 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");
        }
    }
}

Was passiert ist, dass, wenn die currentEmployee Wenn die Eigenschaft festgelegt ist, prüft sie, ob es einen vorherigen Wert gab, und entfernt in diesem Fall die Bindung für dieses Objekt (currentEmployeeNameCW.unwatch()), dann legt es die private Variable fest, es sei denn, der neue Wert war null richtet eine neue Bindung für die ein name Eigentum.Am wichtigsten ist, dass es das spart ChangeWatcher durch den Bindungsaufruf zurückgegeben.

Dies ist ein einfaches Bindungsmuster und ich denke, es funktioniert gut.Es gibt jedoch einen Trick, mit dem man es etwas einfacher machen kann.Stattdessen können Sie sich an sich selbst binden.Anstatt jedes Mal Bindungen einzurichten und zu entfernen currentEmployee Wenn Sie Eigenschaftsänderungen vornehmen, können Sie diese vom Bindungssystem für Sie erledigen lassen.In deinem creationComplete Handler (oder Konstruktor oder zumindest etwas früher) können Sie eine Bindung wie folgt einrichten:

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

Dadurch entsteht eine Bindung nicht nur an die currentEmployee Eigentum auf this, sondern auch zum name Eigentum an diesem Objekt.Also jederzeit entweder die Methode ändern currentEmployeeNameChanged wird angerufen werden.Es besteht keine Notwendigkeit, das zu speichern ChangeWatcher denn die Bindung muss nie entfernt werden.

Die zweite Lösung funktioniert in vielen Fällen, aber ich habe festgestellt, dass die erste manchmal notwendig ist, insbesondere wenn mit Bindungen in Nicht-Ansichtsklassen gearbeitet wird (da this muss ein Event-Dispatcher sein und der currentEmployee muss bindbar sein, damit es funktioniert).

Andere Tipps

Es existiert seit heute.:) :)

Ich habe gerade mein ActionScript-Datenbindungsprojekt als Open Source veröffentlicht: http://code.google.com/p/bindage-tools

BindageTools ist eine Alternative zu BindingUtils (siehe das Wortspiel dort?), die eine fließende API verwendet, bei der Sie Ihre Datenbindungen im Pipeline-Stil deklarieren:

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

Zwei-Wege-Bindungen:

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

Explizite Datenkonvertierung und -validierung:

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

Usw.Es gibt viele weitere Beispiele auf der Website.Es gibt auch viele andere Funktionen – schauen Sie sich um.--Matthew

Bearbeiten:aktualisierte APIs

Eine Möglichkeit, MXML und ActionScript für eine Komponente in separate Dateien aufzuteilen, besteht darin, etwas Ähnliches wie beim ASP.Net 1.x-Code-Behind-Modell zu tun.In diesem Modell ist der deklarative Teil (in diesem Fall MXML) eine Unterklasse des imperativen Teils (ActionScript).Ich könnte also den Code dahinter für eine Klasse wie diese deklarieren:

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.";
        }
    }
}

...und das Markup so:

<?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>

Wie Sie diesem Beispiel entnehmen können, besteht ein Nachteil dieses Ansatzes darin, dass Sie Steuerelemente wie deklarieren müssen myLabel in beiden Dateien.

Es gibt eine Möglichkeit, die ich normalerweise verwende, um MXML und Aktionsskript zusammen zu verwenden:Alle meine MXML-Komponenten erben von einer Aktionsskriptklasse, der ich den komplexeren Code hinzufüge.Anschließend können Sie in der MXML-Datei auf die in dieser Klasse implementierten Ereignis-Listener verweisen.

Grüße,

Ruth

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top