English 中文(简体)
Updating runtime created arraycollections, they all have the same source
原标题:

I have a source collection (now a simple Array). At run-time I create ArrayCollections using the same array as the source (each collection show the same source, but they are differently filtered). My problem is, when a new item added to the source, the already created arraycollections wont updated if one of the property of this new item is updated.

Anyone has a solution to this? What if my source is a Dictionary. How to create different ArrayCollections from the source dictionary, while the collections update whenever new item added, or an item is updated?

thanx

最佳回答

My solution is: Ive created a new class derived from ArrayCollection. Name it SourceCollection. Added a new private member that is a Dictionary, created with weakKeys turned to true. A new public function creates a new ArrayCollection from its elements, and add the reference of this created collection to the private dictionary like:

public function createCollection():ArrayCollection
{
   var result:ArrayCollection = new ArrayCollection();
       result.addAll(this);
   createdCollections[result] = null;
   return result;
}

Overrided the addItemAt, removeItemAt and removeAll function: each calls its super function and iterates through the dictionary, and do the appropriate function. Note addItem and addAll also calls addItemAt, so dont need to override them. One example is:

override public function addItemAt(item:Object, index:int):void
{
   super.addItemAt(item, index);

   for (var coll:Object in createdCollections)
   {
     (coll as ArrayCollection).addItemAt(item, index);
   }
}

Also added a test function that iterates through the dictionary, and count the items. If i dynamically creates Lists and assign ArrayCollection created from source with createCollection function, adding, removeing reflected fine, all has the same source items, that i wanted, and after removing dynamically created lists, after a while, tracked list count decreases automatically.

If you put objects in the source that dispatches propertyChange event on any change, all Lists shows the change, too.

问题回答

The issue is that arrays aren t [Bindable] in Flex. So you have a few options:

  • Make source an ArrayCollection, and addEventListener for CollectionEvent.COLLECTION_CHANGE.
  • Add items to all array collections in some method addItemToCollections to keep them all in sync.

Here is an example of what I am describing:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:local="*"
    creationComplete="creationCompleteHandler()">

    <mx:Script>
        <![CDATA[
            import mx.events.CollectionEvent;
            import mx.events.CollectionEventKind;
            import mx.collections.ArrayCollection;
            import ColorPalette;

            protected function creationCompleteHandler():void
            {
                var item:Object;
                var i:int = 0;
                var n:int = source.length;
                for (i; i < n; i++)
                {
                    item = source[i];
                    collectionA.addItem(item);
                    collectionB.addItem(item);
                    collectionC.addItem(item);
                    bindableCollection.addItem(item);
                }
                bindableCollection.addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler);
            }

            protected function collectionChangeHandler(event:CollectionEvent):void
            {
                switch (event.kind)
                {
                    case CollectionEventKind.ADD :
                        collectionA.addItem(event.items[0]);
                        collectionB.addItem(event.items[0]);
                        collectionC.addItem(event.items[0]);
                    break;
                }
            }

            public function addItem():void
            {
                source.push({name:"new item " + (Math.random()*1000).toString()});
            }

            public function addItemToCollection():void
            {
                var item:Object = {name:"new item " + (Math.round(Math.random()*1000)).toString()};
                collectionA.addItem(item);
                collectionB.addItem(item);
                collectionC.addItem(item);
            }

            public function addToBindableCollection():void
            {
                var item:Object = {name:"new item " + (Math.round(Math.random()*1000)).toString()};
                bindableCollection.addItem(item);
            }

        ]]>
    </mx:Script>

    <mx:Array id="source">
        <mx:Object name="one"/>
        <mx:Object name="two"/>
        <mx:Object name="three"/>
    </mx:Array>

    <mx:ArrayCollection id="collectionA"/>
    <mx:ArrayCollection id="collectionB"/>
    <mx:ArrayCollection id="collectionC"/>
    <mx:ArrayCollection id="bindableCollection"/>

    <!-- sample lists -->
    <mx:Panel id="panel" width="100%" height="100%">
        <mx:Button label="Add Item to Source" click="addItem()"/>
        <mx:Button label="Add Item to Collections" click="addItemToCollection()"/>
        <mx:Button label="Add Item to Bindable Collection" click="addToBindableCollection()"/>
        <mx:HBox width="100%" height="100%">
            <mx:List id="listA" dataProvider="{collectionA}" labelField="name"/>
            <mx:List id="listB" dataProvider="{collectionB}" labelField="name"/>
            <mx:List id="listC" dataProvider="{collectionC}" labelField="name"/>
        </mx:HBox>
    </mx:Panel>

</mx:Application>

Let me know if that helps, Lance

I believe you will need to use ObjectUtil.copy() and make copies of your Array.





相关问题
Disable button tooltip in AS3

I want to disable the tooltip on certain buttons. The tooltip manager seems to be an all or nothing solution. Is it possible to disable the tooltip for just one or two buttons?

Multiple Remote call made simultenously

I was making multiple remote calls and they are done sequentially and when I am getting a result event back it s triggering calls to all the methods with ResultEvent as an argument . I am supposed to ...

Attaching a property to an event in Flex/AS3

I have a parameter that needs to be passed along with an event. After unsuccessful attempts to place it on the type by extending the class, I ve been advised in another SO question to write a custom ...

Clearing RSL in Cache

I have built a flex application which has a "main" project and it is assosciated with a few RSL s which are loaded and cached once i run my "main" application. The problem i am facing is that the ...

What s a good way of deserializing data into mock objects?

I m writing a mock backend service for my flex application. Because I will likely need to add/edit/modify the mock data over time, I d prefer not to generate the data in code like this: var mockData =...

AS3 try/catch out of memory

I m loading a few huge images on my flex/as3 app, but I can t manage to catch the error when the flash player runs out of memory. Here is the what I was thinking might work (I use ???? because i dont ...

热门标签