Flex Data Bindings – Behind The Scenes
Ever wondered how flex data bindings actually work behind the scenes? I have, and sometimes I have had troubles with it, that made me wish I knew some more. This post is a writeup of the knowledge about flex data bindings I uncovered, when looking into the mxmlc generated code for bindings.
Vanilla Example
Here is a dead simple vanilla sample of flex that does a little bit of data binding:
<?xml version="1.0" ?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Script><![CDATA[
[Bindable] public var value: String = "blah";
]]></mx:Script>
<mx:TextInput id="textInput" text="{value}"/>
</mx:Application>
where value is bound into textInput.text will generate quite a bit of supporting code, when being mxmlc’ed. Basically, it seems like flex operates with two concepts behind the scenes: Bindings and Watchers.
Bindings
A Binding is a one-way connection, that can read a value from a source and set it on a destination, but only when explicitly executed. There is not listening for changes built into a binding as such, it is just a mechanism that can be executed by someone, to transfer a value between a source and a destination.
So, how does a binding get executed? It does so, when the Watchers it is connected to fires. A binding acts as listener for watcherFired on a Watcher, which is how it gets executed when changes happen.
Here is the binding setup, that flex generates for the above example:
binding = new mx.binding.Binding(this,
function():String {
var result:* = (value);
var stringResult:String = (result == undefined ? null : String(result));
return stringResult;
},
function(_sourceFunctionReturnValue:String):void {
textInput.text = _sourceFunctionReturnValue;
},
"textInput.text");
basically, it instantiates a mx.binding.Binding with the parameters:
- this which is this context – pun intended – means the FlexTest application class
- a function that can read the source value when executed
- a function that can set the target property when executed
- a textual string of the target (docs says it is used for validation)
this sets up a “channel” from source to target.
Watchers
While Bindings only implement the reading of the source and setting into target, the other big part of flex data bindings is actually determining if and when, a binding should execute. This is where Watchers come in.
A Watcher can watch for changes on something, one typical example is a change of a property value. When such a change is detected, the watcher notifies its listeners (which are Binding instances) about the change. It is then up to the listener (the bindings), to actually read out the source and set the target (aka: Execute the binding). It is the Watcher, that determines if a value has actually changed.
Here is the watcher setup, that flex generates for the above example:
watchers[0] = new mx.binding.PropertyWatcher("value",
{ propertyChange: true },
[ bindings[0] ],
propertyGetter);
as you can see, it instantiates a mx.binding.PropertyWatcher instance, as it is a property we are binding from, with the following parameters:
- a map of event names as keys, that are the event to listen for, when watching changes. This is what can be overridden with [Bindable("otherEventNameHere"])
- an array of listeners, that get called on their watcherFired method when the watcher detects a change (the listeners are Binding instances, and in this context bindings[0] is the exact binding that we saw the code for just before
- and lastly propertyGetter is a method, that can return access to properties in the context watched
I am sure you can image how this works then. By hey, … when is the “propertyChange” event being dispatched in our code. I mean, when you look at the initial example code, if I was to assign a new value to the value property, there sure ain’t any code there, which fires any events.
Well, it turns out mxmlc has generated code for that too:
[Bindable(event="propertyChange")]
public function get value():String {
return this._111972721value;
}
public function set value(value:String):void {
var oldValue:Object = this._111972721value;
if (oldValue !== value) {
this._111972721value = value;
this.dispatchEvent(mx.events.PropertyChangeEvent.createUpdateEvent(this, "value", oldValue, value));
}
}
it simply moves the original value property to a generated name _111972721value and adds a get/set pair on the value name instead. Clever. And hey, look into that setter. It dispatches the propertyChange event, when changed.
October 12, 2009
Tags: data binding, flex Posted in: Programming, Rich Internet Applications

One Response
Thanks for the enlightenment, I really enjoyed the post. Seeing the mxmlc generated code really makes it easier to understand the concepts at work here. I’ve always been curious about what happens behind the scenes with data binding but haven’t taken the time to dig into into. So thanks for doing the legwork.
Leave a Reply