- Data binding is the plumbing (or “out-of-the-box” feature) provided by modern presentation frameworks such as Flex SDK and WPF. The general idea is to facilitate communications concerning value changes among different objects, so that the application developers can focus on higher level tasks. Most of these plumbings are optimized for declarative code (MXML, XAML and metadata tags in your procedural code). For example, if you use [Bindable],<fx:Binding> meta tags or curly braces (MXML data binding expressions), Flex compiler will give compilation warnings about whether it thinks the data bindings you set up will work nor not; while you don’t get this kind of nice friendly reminder if you use mx.binding.utils.BindingUtils or mx.binding.utils.BindingUtils.ChangeWatcher directly.
- Data binding is nothing magical than using event listeners to watch for changes on objects/values and then get the updated values. There are two sides of the equation:A. You tell the compiler which object/value you’d like to watch, like so:
public function get selectedEmployee():Employee
return _selectedEmployee = v;
Here you tell the Flex to get the value for _selectedEmployee whenever the interested parties are notified by the event “selectedEmployeeChanged”. If you don’t specify an event name, flex will automatically associate this data bound value with an event named “propertyChange” and will dispatch that event for you behind the scene. This is convenient for the developer as you don’t need to care about when to fire the event(s) and which event(s) you need to listen for the involved parties, etc..
B. You tell the compiler when the object/value is changed, like so:
public function set selectedEmployee(v:Employee)
_selectedEmployee = v;
dispatchEvent(new Event("selectedEmployeeChanged", true, true));
Here you trigger the data binding (chain) by firing the “selectedEmployeeChanged” event which you defined in step A. Flex then will copy the values for you to the interested parties (destinations of the data binding.)
- To really understand data binding, it’s important to understand under what conditions the compiler will do the work for you (or the opposite, “when data binding is not supported”) when you set up your data binding (using <fx:Binding>, [Bindable] and data binding expressions). It helps to give examples to show when it doesn’t work. Scenario: You want to watch property changes in another class. For example, if I have an object called FacebookStatus and it contains properties such as numberOfLikes and numberOfDislikes (a feature pending further proof by the product manager) and I have another object called UserInfo which contains a FacebookStatus object. If my FacebookStatus object wants to watch changes of numberOfLikes of FacebookStatus, I can’t simply say:
public function set numberOfLikes(v:int)
_numberOfLikes = v;
public function handleUserStatusChange(event:Event):void
//do something to react...
In the example above, UserInfo will never gets notified by “statusChange” as the compiler won’t look into another object to make the [Binding] tag work. In this case, you can do the binding work yourself by using mx.binding.utils.BindingUtils.bindSetter().
- It helps to understand what the data binding doesn’t do as well as the trade-offs of having the compiler doing the data binding for you. Sometimes it’s better to do the work yourself. For example, if you have a Watch object that works somehow like a timer (stores information about the minutes elapsed since certain point of time) and you want to show it on the screen, you have to call a function to constantly get the minutes value (e.g., in a loop) in order to get the UI updated constantly. Merely setting up the data binding from the Watch object to the UI is not sufficient.Also, since the compiler needs to create a lot of listeners under the hook, it can consume much more memory and involves deep function stack calls to eventually get the values copied around.
- If you set up your data binding in <fx:Binding> tags or using [Bindable] metadata tags, Flex sets up the data binding at the “initialization” stage of the UIComponent’s life cycle. It uses try/catch to hide the null objects/values errors and update the values when available.
- If you have a data object with complex properties, which has complex properties, etc., (e.g, employee.supervisor.department.id) and you want to data bind it’s property, then each node in the data binding chain needs to be set up as data bindable. This won’t automatically happen; but the compiler will give a friendly warning about it if it finds any of the properties in the chain is not data bound.
- You can watch for more than one event on a value change:
[Bindable("change")]public function get selectedIndices():Vector.<int>
Here are several interested read (last one in Chinese):
Two-Way Data Binding in Flex 4
Michael Labriola’s presentation entitled Diving in the Data Binding Waters