mx.binding.utils.BindingUtils

| | Save This Page to del.icio.us このエントリーを含むはてなブックマーク

 日頃からFlexライブラリのデータバインディングにはずいぶんお世話になっている。

 データバインディングとは、あるオブジェクトのデータを他のオブジェクトに結びつける機能のことで、主にModelの値をViewに反映するのに使う。

 データバインディングを実現する3つの方法

  1. mxmlで波括弧シンタックスを使う
  2. mxmlでを使う
  3. ActionScriptでmx.binding.utils.BindingUtilsを使う

 1や2は簡単だし便利だけど、mxmlにはUIだけ書くというポリシーから使わない。

 mx.binding.utils.BindingUtilsの2つのメソッド

  1. bindProperty
  2. bindSetter

 bindPropertyは、あるオブジェクトの値が変わったら、他のオブジェクトの値に反映させるようにするメソッド。

 bindSetterは、あるオブジェクトの値が変わったら、オブジェクトの値を引数に取るセッターを呼ぶようにするメソッド。

 Modelの値をViewに反映するのに使う場合、Modelの値をただ反映するケースは稀で、多くはビュー側で何らかの処理を書くことが多い。また、ビュー側で処理を書かないケースでも、きちんとDTOを作るのがめんどくさかったりして、bindPropertyの出番はあまりない。

 

 main.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:local="*"
    xmlns:mx="http://www.adobe.com/2006/mxml"
    layout="absolute">
    <local:View/>
</mx:Application>

 Model.as

package
{
    public class ModelLocator
    {
        //--------------------------------------------------------------------------
        //
        //  Class consts
        //
        //--------------------------------------------------------------------------

        private static var instance:ModelLocator;

        //--------------------------------------------------------------------------
        //
        //  Class methods
        //
        //--------------------------------------------------------------------------

        public static function getInstance():ModelLocator
        {
            if (instance == null)
                instance = new ModelLocator();
            return instance;
        }

        //--------------------------------------------------------------------------
        //
        //  Constructor
        // 
        //--------------------------------------------------------------------------

        public function ModelLocator()
        {
            if (instance != null)
                throw new Error("Public construction not allowed. Use getInstance()");
        }

        //--------------------------------------------------------------------------
        //
        //  Properties
        //
        //--------------------------------------------------------------------------

        private var _test:String;

        [Bindable]
        public function get test():String
        {
            return _test;
        }

        public function set test(value:String):void
        {
            _test = value;  
        }

    }
}

 View.mxml

<?xml version="1.0" encoding="utf-8"?>
<ViewHelper
    xmlns="*"
    xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:VBox>
        <mx:Button id="button" label="getTimer()"/>
        <mx:Text id="text"/>
    </mx:VBox>
</ViewHelper>

 ViewHelper.as

package
{
    import flash.events.MouseEvent;
    import flash.utils.getTimer;

    import mx.binding.utils.BindingUtils;
    import mx.containers.Canvas;
    import mx.controls.Button;
    import mx.controls.Text;
    import mx.events.FlexEvent;

    public class ViewHelper extends Canvas
    {
        public function ViewHelper()
        {
            super();

            addEventListener(FlexEvent.PREINITIALIZE, preinitializeHandler);
            addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
        }

        private var model:ModelLocator = ModelLocator.getInstance();

        private function setData(test:String):void
        {
            if (test == null) return;

            Text(this['text']).text = test; 
        }

        private function preinitializeHandler(event:FlexEvent):void
        {
            BindingUtils.bindSetter(setData, model, 'test');
        }

        private function creationCompleteHandler(event:FlexEvent):void
        {
            Button(this['button']).addEventListener(MouseEvent.CLICK, buttonClickHandler);
        }

        private function buttonClickHandler(event:MouseEvent):void
        {
            model.test = getTimer().toString();
        }   
    }
}

 あまりbindSetterを使う旨味が実感しにくい例だけど、最近の開発スタイルを凝縮して書いてみるとこんな感じ。

 データバインディングで注意した方が良いこと

  1. 監視したい変数には[Bindable]を付ける
  2. プロパティの場合は、getterに付ける

 なお、bindSetterの場合は[Bindable]を付け忘れていても、まるで何事もなかったように何も言われないのでご注意を!

 実は、最後のが言いたかっただけだったりする。

TRACKBACK

このブログ記事を参照しているブログ一覧: mx.binding.utils.BindingUtils

このブログ記事に対するトラックバックURL: http://blog.s2factory.co.jp/MT/mt-tb.cgi/9