Flexデータバインディングのトリック

1年未満前に、Flexでクライアントを作成する必要があるプロジェクトに関与しました。 私はこのビジネスを始めたばかりだったので、仕事の過程で、私にはまったく新しい未知の何かを見つけました。 その時、Flex Data Bindingを発見しました。 Flexを使用するすべての人がすぐにデータバインディングに遭遇すると思います。

データバインディングは、2つのオブジェクト(データソース)を簡単に相互に接続できるため、同期を維持できます。 例としては、いくつかの動作ルールを作成することによるユーザーインターフェイス要素のリンクがあります。これにより、よりインタラクティブなユーザーインターフェイスを作成できます。

この分野である程度の経験があるため、Flexのすべてのタイプのデータバインディングメカニズムを解析することにしました。 この記事は初心者にとってだけでなく、専門家も自分自身で何かを学ぶことができると思います。



MXMLを使用した単純なデータバインディング



(少なくとも私が読んだ)データバインディングに関するすべてのドキュメントは、この素晴らしい機能のこの特定のタイプの使用から始まります。 残念ながら、これは実際のところどこでも明確に説明されている唯一の方法です。 したがって、2つのテキストフィールドがあるとします。



<mx:TextInput id="sourceField" text="" />

<mx:TextInput id="destinationField" text="" />








最初のフィールドの変更を別のフィールドに表示する必要があります。 この状況では、次のmxmlコードを記述するだけで十分です。



<mx:Binding destination="destinationField.text" source="sourceField.text"/>







これにより、最初のテキストフィールドに入力されたテキストが2番目のテキストフィールドに自動的にインストールされます。 これは、単純なデータバインディングの意味です。 データバインディングを使用した簡単なアプリケーションコード:



 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Binding destination="destinationField.text" source="sourceField.text"/> <mx:VBox> <mx:TextInput id="sourceField" text="" /> <mx:TextInput id="destinationField" text="" /> </mx:VBox> </mx:Application>
      
      







ActionScriptを使用したシンプルなデータバインディング



上記の例は、ActionScriptで簡単に書き換えることができます。 この構造の意味は、動的に作成された要素に使用できることです。 したがって、すべて同じ2つのテキストフィールド:



public var sourceField : TextInput = new TextInput();

public var destinationField : TextInput = new TextInput();








これらのフィールドのデータバインディングは次のようになります。



BindingUtils.bindProperty(destinationField, "text", sourceField, "text");







bindProperty関数の最初のパラメーターは「destination」オブジェクト、2番目のパラメーターはこのオブジェクトのプロパティ名の文字列、3番目のパラメーターは「destination」オブジェクト、4番目のパラメーターはチェーンオブジェクトです。 »(このパラメーターについては、以下で詳しく説明します)。 このデータバインディングメソッドを使用するアプリケーションコード:



 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()"> <mx:Script> <![CDATA[ import mx.controls.TextInput; import mx.binding.utils.BindingUtils; public var sourceField : TextInput = new TextInput(); public var destinationField : TextInput = new TextInput(); public function init():void { sourceField.text = ""; parentContainer.addChild(sourceField); destinationField.text = ""; parentContainer.addChild(destinationField); BindingUtils.bindProperty(destinationField, "text", sourceField, "text"); } ]]> </mx:Script> <mx:VBox id="parentContainer"/> </mx:Application>
      
      







BindingUtilsクラスのbindPropertyメソッドのチェーンオブジェクト。



先ほど触れたチェインオブジェクトについて、さらに詳しく考えてみましょう。 このオブジェクトは、BindingUtilsクラスのbindProperty関数の4番目のパラメーターとして使用されます。 このオブジェクトは、「出発点」オブジェクトにデータバインディングを適用する方法とパラメーターを記述します。 このオブジェクトは、3つの異なる形式で表すことができます。



ひも


文字列-「出発点」オブジェクトのプロパティの名前を格納します。 つまり、「sourceField」という名前のテキストフィールドがある場合、オプション「text」の名前をチェーンオブジェクトとして使用できます。 このタイプのチェーンオブジェクトについては、上記で説明しました。 これ以上の説明は冗長です。



文字列の配列


文字列の配列-「出発点」オブジェクトの内部プロパティへのアクセスの階層に格納します。 このタイプのチェーンオブジェクトの目的は、2つのオブジェクトのみを使用する簡単な例を見ると非常に簡単です。



 package src { public class SimpleObject { public var myText:String = new String(); public function SimpleObject():void { myText = "empty"; } } } package src { public class ComplexObject { public var simpleInstance: SimpleObject = new SimpleObject(); public function ComplexObject():void { //some logic } } }
      
      







テキストフィールドを関連付ける必要があるComplexObjectクラスのインスタンスがあると仮定します。つまり、myTextプロパティ(ComplexObjectクラスの内部オブジェクトにある)は、テキストフィールドのtextプロパティに関連付ける必要があります。 初期化コード:



public var destinationField : TextInput = new TextInput();

public var complexInstance : ComplexObject = new ComplexObject();








上記のように、complexInstance.simpleInstance.myTextをdestinationField.textに関連付ける必要があります。 データバインディングでは、これは次のように行われます。

 BindingUtils.bindProperty( destinationField, "text", complexInstance, ["simpleInstance","myText"]);
      
      







この例では、階層配列がチェーンオブジェクトとして使用されます。 将来的には、配列のすべての要素が1行のポイントを介して結合され、「出発点」オブジェクトのプロパティとして使用されます。 このデータバインディングメソッドを使用したアプリケーションの完全なコード:



 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()"> <mx:Script> <![CDATA[ import src.ComplexObject; import mx.controls.TextInput; import mx.binding.utils.BindingUtils; public var destinationField : TextInput = new TextInput(); public var complexInstance : ComplexObject = new ComplexObject(); public function init():void { destinationField.text = ""; parentContainer.addChild(destinationField); BindingUtils.bindProperty(destinationField, "text", complexInstance, ["simpleInstance","myText"]); } ]]> </mx:Script> <mx:VBox id="parentContainer"/> </mx:Application>
      
      







複合オブジェクト


複合オブジェクト-この場合、チェーンオブジェクトは次のタイプのオブジェクトです。



var object : Object = {name:< >, getter: < >};







プロパティ名-「出発オブジェクト」のプロパティの名前を含む行があります

値取得関数-この関数の形式は次のとおりです。



 function (host:<  « » >) : <  > { //         host, //     « » }
      
      







このタイプのチェーンオブジェクトを理解するには、非常に単純なデータバインディングの例を使用できます。 たとえば、ArrayCollectionクラスのインスタンスとテキストフィールドがあります。 タスクの条件は、10個のコレクションに含まれるオブジェクトの数に達したときにテキストフィールドを無効にすることです。 必須変数の宣言:



public var array : ArrayCollection = new ArrayCollection();

public var destinationField : TextInput = new TextInput();








この場合のデータバインディングの使用:

 BindingUtils.bindProperty( destinationField, "enabled", array, { name:"length", getter : function (host : ArrayCollection):Boolean { return host.length<10; } });
      
      







ご覧のとおり、コードはシンプルで簡単です。 この場合、データバインディングは必要な方法で機能します:コレクション内の要素の数が10以上の場合はテキストフィールドを無効にし、それに応じて要素の数が小さい側に変わったときにオンにします。 このデータバインディングメソッドを使用したアプリケーションの完全なコード:



 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; import mx.controls.TextInput; import mx.binding.utils.BindingUtils; public var destinationField : TextInput = new TextInput(); public var array : ArrayCollection = new ArrayCollection(); public function init():void { destinationField.text = "some text"; parentContainer.addChild(destinationField); BindingUtils.bindProperty( destinationField, "enabled", array, { name:"length", getter : function (host : ArrayCollection):Boolean { return host.length>=10; } }); } ]]> </mx:Script> <mx:VBox id="parentContainer"> <mx:Button label="add element" click="array.addItem(0);"/> <mx:Text text="array length: {array.length}"/> </mx:VBox> </mx:Application>
      
      







BindingUtilsクラスのbindSetterメソッド。



データバインディングの別の方法を検討してください。 このメソッドは、「出発点」オブジェクトのプロパティを変更するのと同様のコールバック関数を呼び出すことができるという事実に基づいています。

簡単な例を考えてみましょう。 コレクションとテキストボックスがあるとします。 タスクの条件は次のとおりです。数値はコレクションに格納され、これらの値は外部からコレクションに追加されます。 コレクションのすべての要素の合計をテキストボックスに表示する必要があります(量は常に関連する必要があります)。 つまり データバインディングの観点から、コレクションの長さを変更する場合は、そのすべての要素の合計を再カウントする必要があります。 この場合、BindingUtilsクラスのbindSetterメソッドが使用されます。



開始するには、変数を初期化します。



public var destinationField : TextInput = new TextInput();

public var array : ArrayCollection = new ArrayCollection();








次に、データバインディング操作について説明します。



 BindingUtils.bindSetter(calculateSum , array, "length");  calculateSum   function ( input : <   « »>):void { //  }
      
      







この場合、calculateSum関数の実装は次のようになります。



 public function calculateSum(input : Number):void { var sum:Number = 0; for (var i:int = 0; i<input; i++) { sum += array[i]; } destinationField.text = sum.toString(); }
      
      







つまり すべて予想どおり。 コレクションの長さを変更すると、金額が再計算されます

その要素とテキストボックスに表示されます。

このデータバインディングメソッドを使用したアプリケーションの完全なコード:



 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()"> <mx:Script> <![CDATA[ import mx.collections.ArrayCollection; import mx.controls.TextInput; import mx.binding.utils.BindingUtils; public var destinationField : TextInput = new TextInput(); public var array : ArrayCollection = new ArrayCollection(); public function init():void { destinationField.text = "some text"; parentContainer.addChild(destinationField); BindingUtils.bindSetter(calculateSum , array, "length"); } public function calculateSum(input : Number):void { var sum:Number = 0; for (var i:int = 0; i<input; i++) { sum += array[i]; } destinationField.text = sum.toString(); } ]]> </mx:Script> <mx:VBox id="parentContainer"> <mx:Button label="add element" click="array.addItem(Math.random());"/> <mx:List width="100" height="200" dataProvider="{array}"/> </mx:VBox> </mx:Application>
      
      







チェーンオブジェクトの複合ビューでのbindSetterメソッドの使用



これはデータバインディングの最も複雑な形式ですが、これは理解が非常に難しいことを意味するものではありません。 従来、問題のステートメントに戻りました。

監視対象コンポーネントで発生した変更に関するデータを収集するコレクタークラスを作成する必要があります。 このクラスは、情報オブジェクトの配列(観測されたコンポーネントの幅、高さ、位置)を格納します。

クラスから始めましょう:



 package src { import mx.collections.ArrayCollection; public class Collector { public var array : ArrayCollection; public function Collector():void { array = new ArrayCollection(); } public function collect(str:String):void { array.addItem(str); } } }
      
      







アプリケーションは次のようになります。



 <?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()"> <mx:Script> <![CDATA[ import mx.core.UIComponent; import mx.binding.utils.BindingUtils; import src.Collector; public var collector : Collector = new Collector(); public function init():void { BindingUtils.bindSetter(collector.collect, button, {name:"width", getter: returnInfo}); data.dataProvider = collector.array; } public function returnInfo(host:UIComponent):String { return "width:" + host.width + "; height:" + host.height; } public function changeButton():void { button.width = Math.round(Math.random() * 200); button.height = Math.round(Math.random() * 100); } ]]> </mx:Script> <mx:VBox> <mx:Button label="change" click="changeButton();"/> <mx:List id="data" width="200" height="400" /> <mx:Button id="button" width="200" height="100" label="mybutton"/> </mx:VBox> </mx:Application>
      
      







init()関数、つまり行に注意してください



BindingUtils.bindSetter(collector.collect, button, {name:"width", getter: returnInfo});







ボタンコンポーネントの「幅」プロパティが変更されると、ボタンに関するデータを生成するreturnInfo関数を呼び出し、このデータが自動的にcollector.collect()関数に転送され、それに応じて処理されるという情報が含まれています。



私が伝えたかったのはそれだけです。



ブログAdobe Flex用に特別に作成されたPSトピック。

彼は間違いなくそこに着くと思います。



All Articles