Pages

November 23, 2008

Data Binding Basics

Posted by Jeremy Mitchell
There are many reasons to choose Flex as your development platform for web-based software applications. Everyone is already familiar with Adobe's claim of a superior user experience delivered via Flex's rich client (aka fat or thick client). However, developers and project sponsors alike are drawn to features of the Flex SDK which promote rapid development of feature-rich, robust applications.

Data binding is a great example of one of these features.

Exposed through the MXML API, data bindings allow developers to "bind" the value of one object property (destination property) to the value of another object property (source property) using MXML or MXML + inline ActionScript.

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

<mx:TextInput id="source" />
<mx:TextInput id="destination" />

OR 

<mx:TextInput id="source" />
<mx:TextInput id="destination" text="{source.text}" />
By utilizing data bindings, any change to the value of the source property is immediately reflected in the destination property. It is important to note that data bindings are "one way". Source property changes affect the destination property value but not vice versa.

One benefit of using the <mx:Binding> tag instead of inline ActionScript is the ability to bind a property to multiple source properties. If any of the source properties change so does the destination property.

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

<mx:TextInput id="source"/>
<mx:TextInput id="source2"/>

<mx:TextInput id="destination"/>
However, both methods allow you to perform operations on a source property value or derive a value from the combination of multiple source properties. See Binding Expressions discussed later.

Note: a source property can only be identified for data binding if the object to which it belongs has an id property.

Although it is possible to bind the text property of one TextInput control to the text property of another TextInput control as demonstrated in the previous example, data binding is not limited to such a scenario.

Properties of visual elements may be bound to non-visual elements and vice versa. In fact, an predominant Flex architecture, MVC, relies on the ability to bind visual elements in the "view" to non-visual elements in the "model".

Also, you could bind the text property of a TextInput control to the selectedIndex property of a ComboBox control if you so choose.

Data bindings are not limited to the binding of "like" properties or "like" elements.

Note that data bindings are, however, limited to properties of identical data types or scenarios where type casting is possible. For example, you can bind a property with a data type String (i.e. text property) to a property with a data type of Int (i.e. selectedIndex) since an Int can be implicitly cast to a String. However, the reverse is not true - a property with a data type of Int cannot be bound to a property with a data type of String.

Data binding could also be accomplished by using ActionScript to add an event listener to the source object which listens for a specified event and calls a specified event handler method responsible for changing the destination object's property value to the source object's property value.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">

<mx:Script>
  <![CDATA[
    private function init():void {
      source.addEventListener(KeyboardEvent.KEY_UP,updateValue);
    }
  
    private function updateValue(event:KeyboardEvent):void {
      destination.text = source.text;
    }
  ]]>
</mx:Script>

<mx:TextInput id="source" />
<mx:TextInput id="destination" />
MXML data binding just allows you to do it easier and with less code.

While some may refer to such capabilities as nothing more than "syntactic sugar", most developers can appreciate the convenience and accessibility demonstrated by Flex's MXML implementation of data bindings.

Keep in mind that using MXML to bind data binds the properties to one another at compile time. If you want to bind data at runtime based on a condition, you will have to use ActionScript.

Binding Expressions

A data binding is the simplest form of a binding expression.

More advanced binding expressions combine the use of data bindings with ActionScript operations. Since binding expressions define the value of an MXML attribute, they must return a value and be wrapped in curly braces. Without curly braces, your binding expression will be interpreted as a literal value.

Binding expression are most commonly used to accomplish the following:
  1. Bind the value of one object property to the property of another object (simple data binding)
  2. String concatenation that includes one or more binded properties
  3. Calculations on one or more binded properties
  4. Conditional operations on one or more binded properties
Simple data binding:

<mx:ComboBox id="c" dataProvider="{myArray}" />

<mx:ViewStack id="v" selectedIndex="{c.selectedIndex}">
  <mx:Canvas>
    <mx:Label text="1"/>
  </mx:Canvas>
  <mx:Canvas>
    <mx:Label text="2"/>
  </mx:Canvas>
</mx:ViewStack>

OR 

<mx:ComboBox id="c" dataProvider="{myArray}" />

<mx:Binding source="c.selectedIndex" destination="v2.selectedIndex" />

<mx:ViewStack id="v2">
  <mx:Canvas>
    <mx:Label text="1"/>
  </mx:Canvas>
  <mx:Canvas>
    <mx:Label text="2"/>
  </mx:Canvas>
</mx:ViewStack>
String concatenation:

<mx:TextInput id="fname" />
<mx:TextInput id="lname" />

<mx:Label text="{'First Name: ' + fname.text}" />
<mx:Label text="{'Full Name: ' + fname.text + ' ' + lname.text}" />

OR

<mx:TextInput id="fname" />

<mx:Binding source="{'First Name: ' + fname.text}" destination="destination.text" />

<mx:Label id="destination"/>
Calculations:

<mx:NumericStepper id="quantity" />

<mx:TextInput id="price" />

<mx:Label text="{'Total: ' + quantity.value * Number(price.text)}" />

OR 

<mx:NumericStepper id="quantity" />

<mx:TextInput id="price" />

<mx:Binding source="{'Total: ' + quantity.value * Number(price.text)}" destination="destination.text" />

<mx:Label id="destination"/>
Conditional:

<mx:NumericStepper id="quantity" />

<mx:Label text="{(quantity.value % 2) ? 'Odd' : 'Even'}" />

OR 

<mx:NumericStepper id="quantity" />

<mx:Binding source="{(quantity.value % 2) ? 'Odd' : 'Even'}" destination="destination.text" />

<mx:Label id="destination"/>

1 comment:

data binding said...

Thanks Mr.jeremy mitchell for a useful blog on data binding as it gives us a lot of information about the features of data binding.