13

これまでにほんの少しのFlex開発を行ってきましたが、mxmlファイルよりもプログラムでコントロールを作成するアプローチを好みました。なぜなら(間違っている場合は訂正してください!)両方の方法があります。つまり、クラス機能は別のActionScriptクラスファイルにありますが、含まれている要素はmxmlで宣言されています。

生産性に関してはそれほど大きな違いはないようですが、プログラムでデータバインディングを実行することは、些細なことではないように思われます。mxmlコンパイラがデータバインディング式をどのように変換するかを調べました。その結果、大量のコールバックが生成され、mxml表現よりもはるかに多くの行が生成されます。だからここに質問があります:傷ついた世界を伴わないプログラムでデータバインディングを行う方法はありますか?

4

4 に答える 4

29

MXMLを恐れないでください。ビューのレイアウトに最適です。独自の再利用可能なコンポーネントを作成する場合、ActionScriptで作成すると、もう少し制御できる場合がありますが、再利用できないビューの場合は、MXMLの方がはるかに優れています。より簡潔で、バインディングの設定は非常に簡単です。

ただし、純粋なActionScriptでのバインディングは、それほど面倒である必要はありません。多くのことが行われるMXMLのように単純になることは決してありませんが、それほど多くの労力をかけずに行うことができます。

あなたが持っているBindingUtilsのは、メソッドbindSetterbindPropertyです。私はほとんどの場合前者を使用します。通常、何らかの作業をしたりinvalidateProperties、値が変更されたときに呼び出したりするため、プロパティを設定することはほとんどありません。

知っておく必要があるのは、これら2つがタイプのオブジェクトを返すChangeWatcherことです。何らかの理由でバインディングを削除する場合は、このオブジェクトを保持する必要があります。これが、ActionScriptの手動バインディングをMXMLの手動バインディングよりも少し不便にしている理由です。

簡単な例から始めましょう:

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

これにより、変数内のオブジェクトnameChangedのプロパティが変更されたときにメソッドを呼び出すバインディングが設定されます。このメソッドは、プロパティの新しい値を引数として受け取るため、次のようになります。nameselectedEmployeenameChangedname

private function nameChanged( newName : String ) : void 

この単純な例の問題は、このバインディングを設定すると、指定したオブジェクトのプロパティが変更されるたびに起動することです。変数の値selectedEmployeeは変更される可能性がありますが、変数が以前に指していたオブジェクトに対してバインディングが設定されたままです。

これを解決するには、2つの方法があります。バインドを削除する(そして代わりに新しいバインディングを設定する)ときに、ChangeWatcher返されたものを保持しBindingUtils.bindSetterて呼び出すか、自分自身にバインドします。unwatch最初に最初のオプションを示し、次に自分自身にバインドすることの意味を説明します。

currentEmployeeをゲッター/セッターのペアにして、次のように実装できます(セッターのみを表示)。

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

currentEmployeeプロパティが設定されると、前の値があったかどうかを確認し、その場合はそのオブジェクト()のバインディングを削除し、currentEmployeeNameCW.unwatch()プライベート変数を設定します。新しい値がnull設定されていない限り、新しいバインディングが設定されます。nameプロパティのために。最も重要なのChangeWatcherは、バインディング呼び出しによって返されたものを保存することです。

これは基本的なバインディングパターンであり、正常に機能すると思います。ただし、少し簡単にするために使用できるトリックがあります。代わりに自分自身にバインドすることができます。currentEmployeeプロパティが変更されるたびにバインディングを設定および削除する代わりに、バインディングシステムにそれを実行させることができます。ハンドラー(またはコンストラクター、creationCompleteまたは少なくとも少し早い段階)で、次のようにバインディングを設定できます。

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

currentEmployeeこれにより、のプロパティだけでなく、このオブジェクトthisのプロパティへのバインディングも設定されます。nameしたがって、どちらかを変更すると、メソッドcurrentEmployeeNameChangedが呼び出されます。ChangeWatcherバインディングを削除する必要がないため、を保存する必要はありません。

2番目のソリューションは多くの場合機能しますが、特に非ビュークラスのバインディングを操作する場合は、最初のソリューションが必要にthisなることがあります(イベントディスパッチャーである必要があり、currentEmployeeバインド可能である必要があるため) 。

于 2008-08-18T06:56:22.250 に答える
8

それは今日の時点で存在します。:)

ActionScript データ バインディング プロジェクトをオープン ソースとしてリリースしました: http://code.google.com/p/bindage-tools

BindageTools は、パイプライン スタイルでデータ バインディングを宣言する流暢な API を使用する BindingUtils (言葉遊びを参照してください) に代わるものです。

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

双方向バインディング:

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

明示的なデータ変換と検証:

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

など。サイトにはさらに多くの例があります。他にもたくさんの機能があります - 見に来てください。--マシュー

編集:更新されたAPI

于 2011-04-02T05:58:23.443 に答える
2

コンポーネントのMXMLとActionScriptを別々のファイルに分離する1つの方法は、モデルの背後にあるASP.Net1.xコードと同様のことを行うことです。このモデルでは、宣言型部分(この場合はMXML)は、命令型部分(ActionScript)のサブクラスです。したがって、次のようなクラスのコードビハインドを宣言する可能性があります。

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

...そしてこのようなマークアップ:

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

この例からわかるように、このアプローチの欠点は、両方のファイルでmyLabelのようなコントロールを宣言する必要があることです。

于 2008-08-30T14:54:16.723 に答える
0

私が通常mxmlとアクションスクリプトを一緒に使用する方法があります。すべてのmxmlコンポーネントは、より複雑なコードを追加するアクションスクリプトクラスから継承します。次に、このクラスに実装されているイベントリスナーをmxmlファイルで参照できます。

よろしく、

ルース

于 2009-02-04T14:49:59.940 に答える