tags:

views:

35

answers:

1

Hi,

I'm trying to create a nested list in Flex which will dynamically resize to display all children when the data provider changes.

Here's a simplified example which illustrates the problem:

<mx:Script>
    <![CDATA[
        import mx.collections.ArrayCollection;

        [Bindable]
        public var outer:ArrayCollection = new ArrayCollection(["one", "two", "three"]);

        [Bindable]
        public var inner:ArrayCollection = new ArrayCollection([]);

        public function addInnerListItems () : void {
            inner.addItem("fish");
            inner.addItem("mice");
            inner.addItem("cats");
            inner.addItem("bats");
        }
    ]]>
</mx:Script>

<mx:Button label="Add inner list items" click="addInnerListItems()" />

<mx:List dataProvider="{outer}" rowCount="{outer.length}">
    <mx:itemRenderer>
        <mx:Component>
            <mx:VBox>
                <mx:Label text="{this.data}" />
                <mx:List dataProvider="{outerDocument.inner}" rowCount="{outerDocument.inner.length}">
                    <mx:itemRenderer>
                        <mx:Component>
                            <mx:Label text="{this.data}" />
                        </mx:Component>
                    </mx:itemRenderer>
                </mx:List>
            </mx:VBox>
        </mx:Component>
    </mx:itemRenderer>
</mx:List>

The list sizes remain static when items are added.

If I add variableRowHeight="true" to the outer list then the inner lists will correctly resize. But the outer list itself remains at a fixed size.

How can I have both lists resize automatically to display all children?

Thanks! Stu

A: 

Override the list class and in your new class override the measure method to calculate measuredWidth and measuredHEight to calculate the values as if all list items were renderered on the screen at full size.

Then override updateDisplayList() in the component that contains the embedded list to size the upper list to the measuredWidth and measurdHeight.

I would not take this approach lightly, though. IF you do this you will be rendering all items on the screen, which negates the renderer recycling benefits of using the List class in the first place.

www.Flextras.com
Thanks for the reply! When you say "calculate the values as if all list items were rendered on the screen at full size" do you mean (roughly) that I multiply the number of elements by some pre-defined static height value? I'm assuming I can't ask the elements for their actual height unless they are already displayed on screen. Or am I wrong?
stubotnik
IF you're using variableRowHeight you're going to have to loop over all itemRenderers of the list and calculate the measuredHeight by adding the measuredHeight of each renderer. You may need to read up on the Flex Component LifeCycle and how Flex creates components and their children: http://livedocs.adobe.com/flex/3/html/help.html?content=ascomponents_advanced_2.html
www.Flextras.com
Thanks again. I was hoping for something like you suggest but I thought it wasn't possible after I read this in the List class' indexToItemRenderer() method description: "Because item renderers only exist for items within the set of viewable rows, you cannot use this method for items that are not visible." Is that what you had in mind or is there another way to get my hands on the List's children so I can measure them?
stubotnik
If you're sizing the component to fit all itemRenderers; all elements of your dataPRovider should have an itemRenderer. Otherwise you can play with the http://livedocs.adobe.com/flex/3/langref/mx/controls/listClasses/ListBase.html#offscreenExtraRowsOrColumns property to generate extra itemRenderers for all items in the dataProvider
www.Flextras.com
great stuff - on the right track now. thanks!
stubotnik