Building Data Binding Proxies

Some types of objects and some elements in Flex applications cannot use data binding directly. For example, you cannot use data binding directly with component styles. Yet you can build an elegant solution that uses something called delegation. Delegation is what occurs when a class called a proxy wraps an object, and it passes along requests to the object it wraps. The goal of delegation may be different in different scenarios, but in this case, the goal is to provide a layer of indirection so that the data-binding-enabled proxy can accept requests in place of the object that cannot accept those requests.

A proxy class generally uses the following structure:

package {

    public class ProxyClass {

        private var _object:Object;

        public function ProxyClass(object:Object) {
            _object = object;
        }

        public function method():void {
            _object.method();
        }

    }

}

Obviously, the preceding format is overly simplified, and each proxy class may vary the format slightly. We’ll look at two specific implementations of proxy classes designed to facilitate data binding in the next two subsections. Hopefully you’ll then be able to generalize this solution so that you can apply it to similar scenarios when you need to enable data binding for an object that doesn’t natively support data binding.

Using Data Binding with a Shared Object

You cannot use data binding with shared objects. Yet you can use a proxy to enable data binding. For this example, we’ll use a very simple case in which you want to store one user preference in a local shared object. That one preference is a Boolean value indicating whether to show a form in the application. Of course, you could accomplish this task through ActionScript, yet you could also enable data binding with a proxy class that wraps the shared object. For this example, here’s our proxy class definition:

package com.oreilly.programmingflex.binding.proxies {
    import flash.net.SharedObject;

    [Bindable]
    public class UserPreferences {

        private var _sharedObject:SharedObject;

        // Retrieve the value from the shared object.
        public function get showForm():Boolean {
            return _sharedObject.data.showForm;
        }

        // Assign the value to the shared object, and call flush()
        // to ensure that it writes to disk immediately.
        public function set showForm(value:Boolean):void {
            _sharedObject.data.showForm = value;
            _sharedObject.flush();
        }

        // The class wraps a shared object. Pass the reference to the constructor,
        // and assign that reference to a private property.
        public function UserPreferences(sharedObject:SharedObject):void {
            _sharedObject = sharedObject;
        }

    }
}

Then, you can use the following MXML to demonstrate how the proxy works:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
initialize="initializeHandler(event)">

    <mx:Script>
        <![CDATA[
            import com.oreilly.programmingflex.binding.proxies.UserPreferences;
            import flash.net.SharedObject;

            // Declare a variable for the instance of the UserPreferences
            // class. Make the variable data-binding-enabled with the
            // [Bindable] metadata tag.
            [Bindable]
            private var _userPreferences:UserPreferences;

            // When the application starts construct the UserPreferences object,
            // passing it a reference to a local shared object.
            private function initializeHandler(event:Event):void {
                _userPreferences =
new UserPreferences(SharedObject.getLocal("userPreferences"));
            }

            // This is the function we call via data binding when the
            // shared object's showForm property changes. Toggle the
            // current state.
            private function set toggleForm(value:Boolean):void {
                currentState = value ? null : "hideForm";
            }

        ]]>
    </mx:Script>

    <!-- Define a state that removes the form -->
    <mx:states>
        <mx:State name="hideForm">
            <mx:RemoveChild target="{form}" />
        </mx:State>
    </mx:states>

    <!-- Define a form and a checkbox -->
    <mx:VBox id="vbox">
        <mx:Form id="form">
            <mx:FormHeading label="Form"/>
            <mx:FormItem label="First Name">
                <mx:TextInput id="firstName"/>
            </mx:FormItem>
            <mx:FormItem label="Last Name">
                <mx:TextInput id="lastName"/>
            </mx:FormItem>
        </mx:Form>
        <mx:CheckBox id="showForm" label="Show Form" />
    </mx:VBox>

    <!-- Define data bindings between the checkbox and proxy object as well
         as between the proxy object and the toggleForm() function. -->
    <mx:Binding source="_userPreferences.showForm"
        destination="showForm.selected" />
    <mx:Binding source="showForm.selected"
        destination="_userPreferences.showForm" />
    <mx:Binding source="_userPreferences.showForm" destination="toggleForm" />

</mx:Application>

This example toggles the state, and it remembers the state every time you return to the application because it’s storing the data in the shared object.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset