Binding to Container children in Flex

Jacob Wright
December 29th, 2007

I guess this week is my week for creating AS3/Flex hacks. I created an XML encoder/decoder that will accept a class-map and create your model from your XML and visa-versa. As part of that I have display objects as part of the model that needs saving out. I suppose you could liken it to MXML.

In order for the XML encoder to work with DisplayObjectContainers I had to give it a way to work with an ArrayCollection to add or remove the children. So I subclassed LayoutContainer and gave it a property called "children" which is an ArrayCollection. Then I set up as a listener to it and every time something is added or removed I use the corresponding DisplayObjectContainer methods to update the display. Pretty slick! The only downside is that someone could add anything to the children ArrayCollection and break things since I am expecting DisplayObjects only. I could add error checking and make it fix itself when that happens... maybe another time.

Here's my listener which responds to the "collectionChange" event of children:

protected function onChildrenChange(event:CollectionEvent):void
{
    var i:Number;
    var items:Array = event.items;
    var location:Number = event.location;
    var oldLocation:Number = event.oldLocation;
    var numItems:Number = items.length;
    var child:DisplayObject;
    var propChange:PropertyChangeEvent;
   
    switch (event.kind)
    {
        case CollectionEventKind.ADD:
            for (i = 0; i <numItems; i++)
            {
                child = items[i] as DisplayObject;
                if (child)
                    addChildAt(child, location + i);
            }
            break;
       
        case CollectionEventKind.REMOVE:
            for (i = 0; i <numItems; i++)
            {
                child = items[i];
                if (child)
                    removeChild(child);
            }
            break;
       
        case CollectionEventKind.MOVE:
            setChildIndex(getChildAt(oldLocation), location);
            break;
       
        case CollectionEventKind.REPLACE:
            for (i = 0; i <numItems; i++)
            {
                propChange = items[i] as PropertyChangeEvent;
                var oldChild:DisplayObject = propChange.oldValue as DisplayObject;
                var newChild:DisplayObject = propChange.newValue as DisplayObject;
                if (oldChild && newChild)
                {
                    var index:Number = getChildIndex(oldChild);
                    removeChildAt(index);
                    addChildAt(newChild, index);
                }
            }
            break;
       
        case CollectionEventKind.REFRESH:
            removeAllChildren();
            for each (child in _children)
                addChild(child);
            break;
       
        case CollectionEventKind.RESET:
            removeAllChildren();
            for each (child in _children)
                addChild(child);
            break;
       
        case CollectionEventKind.UPDATE:
            // don't need to do anything
            break;
    }
}

Leave a Reply