Home > Uncategorized > Flex data binding pitfalls

Flex data binding pitfalls


Flex data binding provides a powerful mechanism for reacting to data changes, but it can be exceptionally tricky to debug when it goes wrong. This post is an accumulation of advice gleaned from colleagues, blogs and painful personal experience into how to avoid some of the nastiest of binding woes.

The best place to start is to read Chapter 40 (Data Binding) of the Adobe Flex 3 developer guide; a great introduction to the topic. I’m taking this as assumed reading, so won’t be covering the many tips contained therein.

Let’s jump straight into the gory details…

1) Don’t use constants as Bindable event names.

01 public static const ASK_PRICE_CHANGE : String =
02 "ASK_PRICE_CHANGE";
03
04 // DON'T DO THIS!!!!!
05
06 [Bindable(event=ASK_PRICE_CHANGE)]
07 public function get askPrice():Number
08 {
09 return _askPrice;
10 }
11 public function set askPrice(value : Number) : void
12 {
13 if (value != _askPrice) {
14 _askPrice = value;
15 dispatchEvent(new Event(ASK_PRICE_CHANGE));
16 }
17 }

It’s a great idea in theory, but it doesn’t work. It looks like you’re using the constant here, but it’s just a literal string. If you change the constant value, the binding will not fire.

2) Don’t rely on the execution order of bindings.
You can’t rely on the order staying the same, even if it works for you now. A refactoring of your source file, or changes to the behaviour of future Flex compilers could cause your assumption to fail in future. Here’s a good example:

1 <mx:Panel id="foo"
2 visible="{model.canViewFoo}"
3 includeInLayout="{foo.visible}">
4 ...
5 </mx:Panel>

This worked most of the time in Flex 3.0, but fails very frequently in Flex 3.3. The right way to do it is:

1 <mx:Panel id="foo"
2 visible="{model.canViewFoo}"
3 includeInLayout="{model.canViewFoo}">
4 ...
5 </mx:Panel>

3) Be wary of swallowed exceptions
Exceptions thrown in binding expressions, or in functions called within binding expressions are silently captured by the binding framework.

4) [Bindable(“propertyChange”)] is not the same as [Bindable]
Even though behind the scenes, the default event name is “propertyChange”, if you explicitly refer to it in your [Bindable] tag, the compiler assumes you will be generating the event yourself. If other properties in the same class are bindable, their updates will not trigger a binding update on your property too. Worse yet, if you try and use dispatchEvent(new Event("propertyChange")) in your setter, you will end up with type coercion errors as the binding framework expects events with the name “propertyChange” to actually be of type PropertyChangeEvent. If you actually dispatch a PropertyChangeEvent event, all will be well, however you might as well of just labelled the property [Bindable] in the first place and let the code generator handle the donkey work.

5) Take extra care when using interfaces in binding expression
If you refer to your bindable class via an interface in a binding expression, you need to be aware of the following limitations:

  1. If the [Bindable] event name in your interface is different from the [Bindable] event name in your class, binding events will not fire.
  2. If you have both a getter and setter for a property and no [Bindable] tag in your interface, binding events will not fire.
  3. If you have only a getter for your property and no [Bindable] tag in your interface, binding events will fire. This is just a weird artifact and shouldn’t be relied upon in future.
  4. Be extra extra careful with nested interfaces.

If you wish to refer to your domain objects using interfaces in classes that use bindings, make sure the bindings metadata exactly matches. If you have multiple implements of an interface with different [Bindable] tags, don’t use the interface for binding expressions, as chances are, it won’t work. Instead, use Object and all your different binding implementations will work as expected.

Debugging bindings
When bindings do go wrong, what’s the easiest way to debug them? You can view the generated source, but don’t expect it to be especially enlightening. About the only useful thing you will glean from perusing the source, is to marvel at just how much of it there is.
A more constructive way to debug is to use the undocumented BindingManager class. This shows you when each of your bindings fire. Add the following line to your Application…

1 BindingDebugger.debugComponent(this);

…and include the following class…

01 package
02 {
03 import mx.binding.BindingManager;
04 import mx.binding.IBindingClient;
05 import mx.core.UIComponent;
06 import mx.core.mx_internal;
07
08 use namespace mx_internal;
09
10 // Kudos to Cathal Golden for coming up with this technique
11 public class BindingDebugger
12 {
13
14 private static const BINDINGS_PROPERTY : String =
15 "_bindingsByDestination";
16
17 public static function debugComponent (
18 displayObject : Object, recursive : Boolean = true) : void
19 {
20 if (displayObject is IBindingClient)
21 {
22 var bindings : Object = displayObject[ BINDINGS_PROPERTY ];
23 for ( var binding : String in bindings )
24 {
25 BindingManager.debugBinding(binding);
26 }
27 }
28
29 if (recursive && displayObject is UIComponent)
30 {
31 var component : UIComponent = UIComponent( displayObject );
32 for (var i : int = 0; i < component.numChildren; i++)
33 {
34 debugComponent(component.getChildAt(i), true);
35 }
36 }
37 }
38 }
39 }

…and you should see all your binding expressions traced out to the console with output like this:

Binding: destString = bid.text, srcFunc result = Bid $15.31
Binding: destString = calcSpread.text, srcFunc result = Calc Spread $2.79
Binding: destString = ask.text, srcFunc result = Ask $18.12
Advertisements
  1. January 29, 2014 at 4:07 AM

    12 Valid Reasons to Snoop if You Suspect Your Mate May
    Be Cheating on You. You can delete these plots later down the
    line, once you have more coins and XP and are at a
    high enough level to unlock the things you really want.
    If you take the time to follow the rules here, and you play often for
    the first week or two, there is a very good chance you will be level 20 or above by the end
    of those two weeks.

  1. November 17, 2010 at 9:55 AM

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: