views:

404

answers:

5

Is it possible to specify MXML-esque "binding strings" in ActionScript?

For example, I want to be able to do something like:

MXMLBinding(this, "first_item",
            this, "{myArrayCollection.getItemAt(0)");
MXMLBinding(this, ["nameLbl", "text"],
            this, "Name: {somePerson.first} {somePerson.last}");

Edit: thanks for the responses and suggestions… Basically, it seems like you can't do this. I've dug around and figured out why.

A: 

I could use BindingUtils or ChainWatcher, but then I'd end up with code that looks something like this:

…
    BindingUtils.bindSetter(updateName, this, ["somePerson", "first"]);
    BindingUtils.bindSetter(updateName, this, ["somePerson", "last"]);
…
protected function updateName(...ignored):void {
    this.nameLbl.text = "Name: " + somePerson.first + " " + somePerson.last;
}

Which is just a little bit ugly… And the first example, binding to arrayCollection.getItemAt(0), is even worse.

David Wolever
Curly brace {} binding is specific to MXML, and is not available in pure AS3. BindingUtils is the way to go.
joshtynjala
A: 

Using ChangeWatcher (e.g., via BindingUtils.bindProperty or .bindSetter) is the way to go, yes. I admit it's a strange notation, but once you get used to it, it makes sense, works perfectly and is quite flexible, too.

Of course, you could always wrap those functions yourself somehow, if the notation bugged you -- both methods are static, so doing so in a way that feels more appropriate to your application should be a fairly straightforward exercise.

Christian Nunciato
It's not so much that the notation is strange… It's that it takes a whole lot more code, which is a whole lot more verbose, to accomplish exactly the same thing.
David Wolever
Yeah, I just don't think there's another way, actually.
Christian Nunciato
A: 

Does the first parameter (function) of BindingUtils.bindSetter method accept anonymous methods?

BindingUtils.bindSetter(function()
  {
    this.nameLbl.text = "Name: " + somePerson.first + " " + somePerson.last;
  }, this, ["somePerson", "last"]);

I hate anonymous methods and obviously it's even more uglier - so I won't recommend that even if it works, but just wondering if it works.

Amarghosh
A: 

Never the answer anyone wants to hear, but just manage this stuff with getters/setters in ActionScript. With a proper MVC, it's dead simple to manually set your display fields.

public function set myArrayCollection(value:Array):void {
  myAC = new ArrayCollection(value);
  first_item = mcAC.getItemAt(0);  // or value[0];
}

etc....

Glenn
The difficulty, though, is this won't bind to `myAC[0]`… To do that, I've got to add a `ChangeListener`, to myAC, and… (well, you know the rest of that story).
David Wolever
I guess my point is that programmers have been managing without binding for a long time. Usually a good architecture is sufficient. You might need a notification system where you can react to changes inside your AC.
Glenn
A: 

Alright, so I've done some digging, and here's what's up.

Bindings in MXML are, contrary to reason, setup by Java code (modules/compiler/src/java/flex2/compiler/as3/binding/DataBindingFirstPassEvaluator.java, if I'm not mistaken) at compile time.

For example, the binding: first_item="{myArrayCollection.getItemAt(0)}"` is expanded into, among other things, this:

    // writeWatcher id=0 shouldWriteSelf=true class=flex2.compiler.as3.binding.PropertyWatcher shouldWriteChildren=true
    watchers[0] = new mx.binding.PropertyWatcher("foo",
                                                 { propertyChange: true }, // writeWatcherListeners id=0 size=1
                                                 [ bindings[0] ],
                                                 propertyGetter);

    // writeWatcher id=1 shouldWriteSelf=true class=flex2.compiler.as3.binding.FunctionReturnWatcher shouldWriteChildren=true
    watchers[1] = new mx.binding.FunctionReturnWatcher("getItemAt",
                                                       target,
                                                       function():Array { return [ 0 ]; },
                                                       { collectionChange: true }, 
                                                       [bindings[0]],
                                                       null);

    // writeWatcherBottom id=0 shouldWriteSelf=true class=flex2.compiler.as3.binding.PropertyWatcher
    watchers[0].updateParent(target);

    // writeWatcherBottom id=1 shouldWriteSelf=true class=flex2.compiler.as3.binding.FunctionReturnWatcher
    // writeEvaluationWatcherPart 1 0 parentWatcher
    watchers[1].parentWatcher = watchers[0];
    watchers[0].addChild(watchers[1]);

This means that it is simply impossible to setup curly-brace MXML-style bindings at runtime because the code to do it does not exist in ActionScript.

David Wolever