views:

3819

answers:

3

Hi

I have a List that uses a custom ItemRenderer. Is there a way for the owner (List) to dispatch a custom event I have created, to all instances of it's ItemRenderer?

For example, I want to dispatch an event that will add text to a textbox within the item renderer. One or more item renderers will be able to respond to this event depending on certain user interactions.

Is there a way?

Thanks :)

+2  A: 

If your custom ItemRenderer instances have access to the List instance somehow, it's straigh forward - just register your event handling method:

theList.addEventListener(YourCustomEvent.CUSTOM_EVENT, itemRendererCustomHander);

If you don't have direct access (which I assume), you can still do it indirectly, e.g. through a delegate of the ItemRenderer's class object. Make an instance of a subclass of EventDispatcher a static property of the ItemRenderer class, and in your ItemRenderer constructor, register an event handler with it:

public class ItemRenderer {
    public static var eventDelegate:YourCustomEventDispatcher;

    public function ItemRenderer() {
        eventDelegate.addEventListener(YourCustomEvent.CUSTOM_EVENT, itemRendererCustomHander);
        (...)
    }

    public function itemRendererCustomHander(event:YourCustomEvent) {
        (...)
    }
}

Now, when you create theList (either in ActionScript or in the initialize event handler of your MXML component), make a new YourCustomEventDispatcher, give to it a reference to theList, and add it to ItemRenderer. YourCustomEventDispatcher registers a private event handler for YourCustomEvent with theList, and just redispatches it. Since all ItemRenderer instances have in turn registered for YourCustomEvent with YourCustomEventDispatcher, theLists's YourCustomEvent reaches all ItemRenderers via one hop.

This is basically an implementation of the Observer design pattern.

Simon
+2  A: 

To access the List instance and add the event listener, your renderer could implement the IDropInListItemRenderer interface.

You will then be forced to implement the get listData and set listData methods defined by the interface. This method will be automatically called by the framework when your instances of the renderer class are required to render a new item, and the set listData will provide you with a BaseListData object with some useful information.

public function set listData(listData:BaseListData):void {
  var list:UIComponent = listData.owner; // the list component instance
  list.addEventListener(YourCustomEvent.CUSTOM_EVENT, itemRendererCustomHander);
}

Note that, when using more complex list-based components (such as DataGrid, AdvancedDataGrid and TreeList, you could safely cast the BaseListData object to more specific classes (DataGridListData, TreeListData, ...) in order to access a set of other information about the context in which this item renderer instance is being used (for example, which column of the DataGrid it is going to render).

Cosma Colanicchia
Nice, this is the direct access thing I did not know until now :-) It's even better than my solution above because you can have multiple Lists with the same ItemRenderer class and do not need to setup multiple eventDelegates.
Simon
Exactly :) Flex item renderers architecture is pretty powerful.. altought I'd like to know which use cases could require item renderer to listen for events from the list component..
Cosma Colanicchia
A: 

very nice tutorial i appreciate it