1
votes

I am using a spark List and wanted to maintain the selection after changing the content of the list that is the data provider. If you set a new data provider the List sets its selectedIndex back to -1. We solved this problem by intercepting the valueCommit event that is fired when teh List wants to set itself back to -1 and setting the previously selected item (if the new data provider still contains it). This works so far but we are getting strange behaviour:

  • initially the previously selected item is still selected and highlighted as intended
  • if another item is selected, the highlighting stays on the intial item. It doesn't matter how often I select another one, the initial item is still highlighted but not selected. The newly selected item is in fact selected and also highlighted.
  • if the initial item is selected again the List is behaving normal again. When I select another item after I reselected the initial one once, the highlighting disapears.

The List is declared in an MXML like this:

<s:List dataProvider="{model.dataProvider}"
selectedIndex="@{model.selectedIndex}"
valueCommit="model.handleInputObjectListValueCommit(event)"/>

The code in the model class is very complex but this should be the relevant part:

[Bindable]
public var dataProvider:ArrayCollection;

[Bindable]
public var selectedIndex:int;

private var _indexToSelect:int = -1;

public function setNewContent(newContent:ArrayCollection):void {

    undoManager.ignore(function ():void {

        dataProvider.removeAll();
        dataProvider.addAll(newContent);

        _indexToSelect = selectedIndex;
    });
}

public function handleValueCommit(event:Event):void {
    if (_indexToSelect != -1) {
        const localIndex:int = _indexToSelect;
        _indexToSelect = -1;
        selectedIndex = localIndex;
    }
}

The undManager is a class that takes care of undo/redo. The ignore function takes care that the undoManager doesn't register the change in the dataProvider as an undoable action because only user interaction should be undoable.

any ideas?

3
Thanks for all your answers. Looks like I'm not getting around posting some code. I will do this later because it could take some time to simplify it for posting.André Stannek
Just noticed my initial question was not entirely correct. I am not setting a new data provider, I am empting the existing one and refilling it. Must have confused it with another problem I had. Sorry for that!André Stannek

3 Answers

1
votes

I got the described result when capturing change events, and fixing it there would require either a hackish solution or a custom UI component to fix what seems like a bug in the List component. But it seems to work if you handle the logic as you change the data provider rather than trying to capture events:

public function setDataProvider(data:IList):void {
    var previous:Object = theSparkList.selectedItem;
    theSparkList.dataProvider = data;
    var index:int = theSparkList.dataProvider.getItemIndex(previous);
    if (index > -1) {
        theSparkList.selectedIndex = index;
    }
}

This might still require some refactoring, and it might not work with your architecture- you might have to provide more detail on that. Is capturing events the only choice?

0
votes

Maybe when changing the dataProvider, re-instantiate the list control ...... list = new List();, or something along those lines to clear the settings for that control.

0
votes
<?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"
               creationComplete="_creationCompleteHandler()">
    <s:layout>
        <s:HorizontalLayout />
    </s:layout>
    <fx:Declarations>
        <s:ArrayList id="d1">
            <fx:Object label="Obj1" />
            <fx:Object label="Obj2" />
            <fx:Object label="Obj3" />
            <fx:Object label="Obj4" />
            <fx:Object label="Obj5" />
            <fx:Object label="Obj6" />
            <fx:Object label="Obj7" />
            <fx:Object label="Obj8" />
            <fx:Object label="Obj9" />
            <fx:Object label="Obj10" />
            <fx:Object label="Obj11" />
            <fx:Object label="Obj12" />
            <fx:Object label="Obj13" />
            <fx:Object label="Obj14" />
        </s:ArrayList>

        <s:ArrayList id="d2">
            <fx:Object label="AA1" />
            <fx:Object label="AA2" />
            <fx:Object label="AA3" />
            <fx:Object label="AA4" />
            <fx:Object label="AA5" />
            <fx:Object label="AA6" />
            <fx:Object label="AA7" />
            <fx:Object label="AA8" />
            <fx:Object label="AA9" />
        </s:ArrayList>
    </fx:Declarations>

    <fx:Script>
        <![CDATA[
            import mx.collections.IList;
            import mx.events.PropertyChangeEvent;
            import spark.events.IndexChangeEvent;

            [Bindable]
            public var listDataProvider:IList;

            private var _lastSelectedItemIndex:int = -1;

            private function _creationCompleteHandler():void
            {
                list.addEventListener(IndexChangeEvent.CHANGE, _list_changeHandler);

                addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, _propertyChangeHandler);
                listDataProvider = d1;
            }

            private function changeButt_clickHandler():void
            {
                listDataProvider = d2;
            }

            private function _propertyChangeHandler(event:PropertyChangeEvent):void
            {
                list.selectedIndex = _lastSelectedItemIndex;
            }

            private function _list_changeHandler(event:IndexChangeEvent):void
            {
                _lastSelectedItemIndex = list.selectedIndex;
            }
        ]]>
    </fx:Script>

    <s:List id="list"
            dataProvider="{listDataProvider}"
            height="200" />
    <s:Button label="changeButt"
              click="changeButt_clickHandler()" />
</s:Application>