David Wolever
David Wolever

Reputation: 154504

Flex: Binding to an MXML-esque "binding string" in action script?

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.

Upvotes: 1

Views: 903

Answers (6)

qualidafial
qualidafial

Reputation: 6822

(Shameless plug)

BindageTools can do this:

Bind.fromProperty(this, "myArrayCollection", itemAt(0))
    .toProperty(this, "first_item");

Bind.fromAll(
    Bind.fromProperty(this, "somePerson.first"),
    Bind.fromProperty(this, "somePerson.last")
    )
    .format("Name: {0} {1}")
    .toProperty(this, "nameLbl.text");

Note that BindageTools puts the source object first and the destination last (whereas BindingUtils puts the destination first and the source last).

Upvotes: 2

David Wolever
David Wolever

Reputation: 154504

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.

Upvotes: 0

Glenn
Glenn

Reputation: 5342

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....

Upvotes: 0

Amarghosh
Amarghosh

Reputation: 59451

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.

Upvotes: 0

David Wolever
David Wolever

Reputation: 154504

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.

Upvotes: 0

Christian Nunciato
Christian Nunciato

Reputation: 10409

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.

Upvotes: 0

Related Questions