views:

349

answers:

1

In the code below, the presentedAlbumIndex is used to control the selectedIndex of the TileList. Item "five" is initially selected. Whenever the button is pressed the first item in the array is deleted, and the presentedAlbumIndex is decremented.

In theory, the selected index should stay with "five" every time the button is clicked (until "five" is itself deleted). It works this way for the first button press. However, on the 2nd button press the highlighting changes to "six" for some reason. Also, the TileList selectedIndex is always one behind.

Why?

I tried looking into ListBase and monitoring selectedIndex. It looks like the selectedIndex is updated initially to the correct index, but then it reverts back at some point to the correct index+1. I do not know why it's setting back.

It seems it's due to the fact that I am doing a data provider delete and index change in the same operation.

Is there some function in TileList I could override to keep selectedIndex up to date?

Steve

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="absolute"
        applicationComplete="init()">
    <mx:Label id="label1" text="{'TileList selected index: ' + albumsThumbnailList.selectedIndex}"
        x="255" y="55" width="234"/>
    <mx:Label id="label2" text="{'Presented album index: ' + presentedAlbumIndex}" x="255" y="81" width="234"/>
    <mx:TileList id="albumsThumbnailList" direction="vertical"
        dataProvider="{presentedAlbums}"
        selectedIndex="{presentedAlbumIndex}" x="25" y="13"
        change="presentedAlbumIndex=albumsThumbnailList.selectedIndex"
        height="400"/>
    <mx:Button click="test2()" x="297" y="150"/>

    <mx:Script>
        <![CDATA[
            import mx.events.CollectionEvent;
            import mx.collections.ArrayCollection;
            private var _includedAlbums:ArrayCollection = new
                ArrayCollection(["zero","one","two","three","four","five","six","seven"]);

            [Bindable]
            private var presentedAlbumIndex:int = 5;

            private function init():void {

                _includedAlbums.addEventListener(CollectionEvent.COLLECTION_CHANGE,
                    function():void {
                        dispatchEvent(new Event("albumDataChanged"));
                    }
                );
            }

            public function test2():void {
                _includedAlbums.removeItemAt(0);
                presentedAlbumIndex--;
            }

           [Bindable(event="albumDataChanged")]
           public function get presentedAlbums():ArrayCollection {
               return _includedAlbums;
           }

        ]]>
    </mx:Script>

</mx:Application>
A: 

With the COLLECTION_CHANGED listener the List gets a new dataProvider, since this is an async event it fires after the binding on the selectedIndex. By removing this listener and not providing a new collection dataProvider whenever the collection changes, the selectedIndex binding functions as expected.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
        layout="absolute"
        applicationComplete="init()">
    <mx:Label id="label1" text="{'TileList selected index: ' + albumsThumbnailList.selectedIndex}"
        x="255" y="55" width="234"/>
    <mx:Label id="label2" text="{'Presented album index: ' + presentedAlbumIndex}" x="255" y="81" width="234"/>
    <mx:TileList id="albumsThumbnailList" direction="vertical"
        dataProvider="{presentedAlbums}" x="25" y="13" 
        selectedIndex="{presentedAlbumIndex}"
        height="400"/>
    <mx:Button click="test2()" x="297" y="150"/>

    <mx:Script>
        <![CDATA[
            import mx.events.CollectionEvent;
            import mx.collections.ArrayCollection;
            private var _includedAlbums:ArrayCollection = new
                ArrayCollection(["zero","one","two","three","four","five","six","seven"]);

            [Bindable]
            private var presentedAlbumIndex:int = 5;

            private function init():void {

            }

            public function test2():void {
                _includedAlbums.removeItemAt(0);
                presentedAlbumIndex--;
            }

           [Bindable(event="albumDataChanged")]
           public function get presentedAlbums():ArrayCollection {
               return _includedAlbums;
           }

        ]]>
    </mx:Script>

</mx:Application>
Joel Hooks
Nope, still get the same issue when calling refresh() prior to decrementing the index. I don't bind directly to _includedAlbums because in my real app the TileList is in a separate class.
Stephen Horvath
Removing the COLLECTION_CHANGED listener makes it function correctly. Is that mandatory.
Joel Hooks
The COLLECTION_CHANGE is required in my case. I am using the COLLECTION_CHANGE event to notify listeners of activities deep inside of the data-provider hierarchy. In my app I actually have other bindings also set on presentedAlbums, and they all cause the issue with selectedIndex not updating.The COLLECTION_CHANGE event is async and fires afterward - that explains why the selectedIndex is getting decremented and then re-incremented. Any idea where in ListBase the data-provider re-incrementation occurs? Maybe I can override it to not update the selected index.
Stephen Horvath
There isn't anything wrong with using COLLECTION_CHANGED, just don't use it for the binding the dataProvider to a function.It is decrementing the selectedIndex in: protected function collectionChangeHandler(event:Event):voidBeast of a function there...
Joel Hooks