views:

44

answers:

2

What I have is a class with static properties that I want to use as images. I would like the images to be configurable at run time but still have the defaults. So the Images class looks like:

package {
public class Images {

[Embed(source="/assets/Green-Light.gif")]
[Bindable]
public static var GreenLight:Class;
}
}

And now a custom component:

package {
import mx.binding.utils.BindingUtils;
import mx.controls.Image;

import spark.components.HGroup;

public class MyComp extends HGroup {
    private var _image:Image;

    public function MyComp() {
        _image = new Image();
        _image.source = Images.GreenLight;
        addElement(_image);
        BindingUtils.bindSetter(setImageIcon, Images, "GreenLight");
    }

    private function setImageIcon(newIcon:Class):void {
        trace(newIcon);
        _image.source = newIcon;
    }
}
}

Now if I create an application like this:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
           xmlns:s="library://ns.adobe.com/flex/spark"
           xmlns:mx="library://ns.adobe.com/flex/mx"
           minWidth="955"
           minHeight="600"
           xmlns:ns1="*">
<fx:Script>
    <![CDATA[
        [Embed(source="/assets/Yellow-Light.gif")]
        [Bindable]
        public var YellowLight:Class;
    ]]>
</fx:Script>
<mx:Image source="{Images.GreenLight}"/>
<s:Button x="10"
          y="40"
          label="Button"
          click="Images.GreenLight=YellowLight"/>
<ns1:MyComp x="40" y="0"/>
</s:Application>

Clicking the button will change the static property in the Images class to something else. The image defined in the MXML will get the binding event and update the image, but the custom component created in ActionSctipt will not be updated.

My question is why? and how do I fix it?

Thanks!

+1  A: 

static variables are made bindable using special magic with generated EventDispatcher-s and StaticPropertyWatcher. If you want to go deep in this, add -keep compiler option.

That's why BindingUtils.bindSetter does not work.

Not sure that you really want to know how to fix this using bindind classes :) Much easier is to bind to Image instance.

Maxim Kachurovskiy
That was something I considered, but why would it work in MXML?
Ryan
I've edited answer, thank you for the question.
Maxim Kachurovskiy
The reason I wanted to have them static was so the images could change at run time and the changes would be reflected in all parts of the application. So I guess the solution is to make it a singleton.
Ryan
+1  A: 

From the looks of the generated code it's not worth trying to figure out how AS is doing it's magic. In that case the best (easiest) option is just to turn the Images class into a Singleton like this:

package   {

public class Images {
    private static var _self:Images;
    public static function getInstance():Images {
        if(_self == null) {
            _self = new Images();
        }
        return _self;
    }
    [Embed(source="/assets/Green-Light.gif")]
    [Bindable]
    public var GreenLight:Class;
}
}

And the MyComp class will do the binding like:

BindingUtils.bindSetter(setImageIcon, Images.getInstance(), "GreenLight");

Thanks to Maxim for the advice.

Ryan