سؤال

It appears as though the new spark List component does not honour the IDropInItemRenderer interface.

Ie - if I implement IDropInItemRenderer on my renderer, the setter of listData is never called.

Am I missing something, or is this interface now deprecated?

If so, What is the suggested approach for providing similar dataProvider context information to the renderer?

For example, I want the renderer for the last item in a collection to behave slightly differently.

I see that IItemRenderer now defines a listIndex property, however this approach doesn't work without knowing the count of the source dataProvider.

هل كانت مفيدة؟

المحلول

Here's the workaround I've ended up using.

In it's own way, the DataGroup is dripping Spark's compositional goodness, in that it exposes a rendererUpdateDelegate property, which you can set with your own class to provide whatever custom functionliaty you're after.

While it's frustrating that the interface got dropped without really being advertised, this approach is much more powerful.

Here's an example class. In my example, I want the last renderer to have it's collapsable property set to false:

/**
 * Decorates another IItemRendererOwner (eg., a DataGroup) and augments the updateRenderer method
 * to set the isCollapsable property */
public class ThreadMessageRendererUpdateDelegate implements IItemRendererOwner
{
    private var _dataGroup:DataGroup;

    public function get dataGroup():DataGroup
    {
        return _dataGroup;
    }

    public function set dataGroup(value:DataGroup):void
    {
        _dataGroup = value;
        if (dataGroup)
        {
            dataGroup.rendererUpdateDelegate = this;
        }
    }


    public var dataProvider:ArrayCollection;

    public function ThreadMessageRendererUpdateDelegate(owner:DataGroup=null)
    {
        this.dataGroup = owner;
    }

    public function itemToLabel(item:Object):String
    {
        return dataGroup.itemToLabel(item);
    }

    public function updateRenderer(renderer:IVisualElement, itemIndex:int, data:Object):void
    {
        dataGroup.updateRenderer(renderer,itemIndex,data);
        if (renderer is ThreadMessageRenderer)
        {
            ThreadMessageRenderer(renderer).collapsable = itemIndex < dataProvider.length - 1;
        }
    }
}

And here's it's example usage:

<fx:Declarations>
    <viewer:ThreadMessageRendererUpdateDelegate dataProvider="{dataProvider}" dataGroup="{threadList}" />
</fx:Declarations>
<fx:Script>
    <![CDATA[
        [Bindable]
        public var dataProvider:ArrayCollection
    ]]>
</fx:Script>
    <s:DataGroup height="100%"
                 width="100%"
                 dataProvider="{dataProvider}"
                 itemRenderer="ThreadMessageRenderer"
                 id="threadList"
                 >
    </s:DataGroup>

نصائح أخرى

Man! Just spent ages trying to find DataGroup.rendererUpdateDelegate(...), eventually discovering why I couldn't, courtesy of this SO post.

Anyway, thinking about the (disappearance of) rendererUpdateDelegate property and your offering a little bit more, I realise neither are really necessary.

DataGroup has the rendererAdd event which gives you enough info, at the right time, to do what you want; for example:

...

<s:DataGroup id="dg"
    dataProvider="{model.dataProvider}"
    itemRenderer="{model.itemRendererFactory}"
    rendererAdd="model.updateRenderer(event.data, event.index, event.renderer)">

...

...and in the model we have:

public function updateRenderer(data:Object, index:int, renderer:IVisualElement):void
{
    if (renderer is ICollapsable)
    {
        ICollapsable(renderer).collapse = index < dataProvider.length - 1;
    }
}

Fewer lines of code and clearer intent

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top