Home >
Getting Control of Flex Data Binding
Databinding in Flex is one of the features that has made it so popular as a Framework. You change a property in one place and, voilà, some text changes in a completely different place. However, there is a lot of backing code that goes into making that magic happen. The Adobe engineers did a great job making sure that most of the time we don't need to know or care exactly how this works, but on occasion it can be helpful to pull back the curtain a bit and take a closer look.
Bindings on read-only properties
Sooner or later, pretty much everyone who uses Flex will get the error “[Bindable] on a read-only getter is unnecessary and will be ignored” when we try to make a read-only property bindable. Because so many people encounter this problem, you probably already know that the solution is to use [Bindable (event="someEvent")] and dispatch a "someEvent" event when you want Flex to update your read-only property.
But you may not have considered the line of thinking that leads to this error message. The Flex engineers are expecting such a Class to look like this:
public Class MyClass {
private var _spacing:int;
private var _height:int;
function MyClass(spacing:int) {
_spacing = spacing;
}
public function get height():int {
return _height;
}
public function set height (value:int):void {
_height=value;
}
public function get spacing():int {
return _spacing;
}
}
And, as a matter of fact, you can bind to spacing on a class that looks like this with no problem and no binding warnings. However, your class probably looks more like this:
public Class MyClass {
private var _spacing:int;
private var _height:int;
private var _numObjects:int=5;
function MyClass() {
super();
}
public function get height():int {
return _height;
}
public function set height (value:int):void {
_height=value;
_spacing= Math.floor(_height/_numObjects);
}
[Bindable]
public function get spacing():int {
return _spacing;
}
}
To the Flex Engineers, if your property is read-only, you probably set the property in the constructor and will never change it, hence the error message that is not helpful with your class implementation. You're doing something the Flex engineers didn't expect you to do with a property that only has a getter–you changed it in response to something else going on in the class. So if that's not how you wrote your class, you need to tell them by dispatching binding events yourself.
This thought process holds the seeds of the solutions to the next problem.
Turning off "Warning: Unable to bind to property" warnings without generating default binding code
Consider a situation where you have a Value Object "SomeObject" that is part of a collection of SomeObjects. Throughout the lifespan of a SomeObject, you may know that you will never change the value of its properties. However, you need to bind to the current SomeObject so that as you inspect different SomeObjects, the properties of the relevant one will be displayed. What's the quickest way to write a SomeObject Class? Probably something like this:
Class SomeObject {
public var foo:String;
public var bar:int;
}
The problem with that is that, when you bind to {currentSomeObject.foo}, you'll get a warning that Flex can't bind to property "foo" on an object with static type SomeObject. If you simply make SomeObject as a Class or its properties bindable with a plain [Bindable] tag, Flex will generate a lot of extra code for you that will never be used and will bloat your class.
There are two ways to turn off the error, while avoiding the code bloat.
The first way is to simply add a [Bindable (event="eventThatWillNeverBeDispatched")] tag above the class declaration. This works, but you could potentially run into problems down the line if someone decides those properties ought to be changed, after all.
The second way is to suck it up and actually do the extra typing to make the properties immutable, like the spacing property in the MyClass example above. Keep in mind that another tradeoff you face by doing this is a long constructor argument list is harder to work with every time you consume the Class.
Prevent Binding to a MXML component
This is one I actually stumbled on by mistake, but some of my favorite tricks are things that were initially screwups that I resolved to turn toward the good. If you write template components or use Code Behind, you have probably set up a property that was not instantiated in the base class–instead, the instance is provided by a MXML component
One way that you can then populate this property is by creating an object in the MXML of the extending class that has the property name as its ID. For example, in Paul Williams' Code Behind Example, if you view the source and go to the AlbumBrowserClass.as file, you can see that the first property, artist, is a public variable of type TextInput. In AlbumForm.mxml, you can see a TextInput with an id of "artist" that provides the actual TextInput to populate that variable.
In Paul Williams' example, the entire class is bindable. However, if it were not, and the artist variable in the Code Behind file were not, you could not bind to the text of artist. This is because Flex respects the Bindable status of the place the variable is declared, not the place the variable is populated. Even though MXML objects are nearly always bindable, it is only nearly, not always.
So, if you want to prevent binding to a MXML component, this is how you do it. Or, more likely, if you can't figure out why your MXML component is not bindable, this is why.
Keep in mind that there is a second way to populate the property, which is to use a MXML tag with a name of the property type that contains an instance of the correct type. This avoids the problem of the object's possibly becoming not bindable. It also avoids a separate problem in the case where you use a subclass of the declared type of the variable. The compiler will not allow you to refer to any properties or methods in MXML that the declared type does not have. For example, in AlbumForm.mxml, another way he might have populated artist is :
<view:artist>
<mx:TextInput width="300" />
</view:artist>
How about you? Do you have any cool binding tricks?




Facebook Application Development
To be honest the very best binding trick I ever did was to stop binding. Binding was one of those magical things in Flex that brought in so many people and got things to happen really fast. And it IS a powerful tool. But I wasn't always responsible with it and ended up with some VERY long binding strings. And race conditions. I'm not saying everyone should give up on binding, but for me I started writing much cleaner code when I minimized my binding. RobotLegs/View Mediators very much helped me to achieve this.
When I do bind then I more frequently use the BindingUtils class in code instead of the "{}"'s in MXML. And when I DO add bindings to my view code I keep it as SIMPLE and STRAIGHT FORWARD as I can. No more magic bindings. They always end up toppling down.
In your sentence:
"For example, in Paul Williams' Code Behind Example, if you view the source and go to the AlbumBrowserClass.as file, you can see that the first property, artist, is a public variable of type TextInput."
I think you meant to say "AlbumFormClass.as" instead of "AlbumBrowserClass.as."
David Salahi
In your sentence:
"For example, in Paul Williams' Code Behind Example, if you view the source and go to the AlbumBrowserClass.as file, you can see that the first property, artist, is a public variable of type TextInput."
I think you meant to say "AlbumFormClass.as" instead of "AlbumBrowserClass.as."
David Salahi