Archive for Wrzesień, 2010

Reakcje i itemrenderer-y w Fabrication

Framework fabrication posiada w swym arsenale ciekawy mechanizm odpowiadający za rejestrację zdarzeń dla komponentów obsługiwanych przez mediatory (klasy komunikujące się z komponentami wizualnymi). Reakcje, bo o nich tutaj mowa są obiektami mającymi za zadanie przypisanie do obiektu "handlera" – funkcji, która zostanie wykonana gdy wystąpi wybrane zdarzenie.

W prezentowanym wpisie chciałbym się jednak skupić nie na samych zaletach reakcji (sposób implementacji i wykorzystania), ale o specyficznej sytuacji w której zachodzi potrzeba obsługi poprzez Reakcje zdarzeń zachodzących w itemrenderer-ach kontrolek flex-owych.

Załóżmy, że potrzebujemy kontrolki DataGrid w której jedna z kolumn powinna zawierać CheckBox-a. Kontrolka zostaje umieszczona w kontenerze Group dla którego rejestruje mediator. CheckBox posiada zdarzenie "change", którego obsługą jesteśmy zainteresowani wewnątrz mediatora.

W chwili obecnej sytuacja implementacyjnie wygląda następująco

Komponent mediatora

<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009"
         xmlns:s="library://ns.adobe.com/flex/spark"
         xmlns:mx="library://ns.adobe.com/flex/mx">
    <s:layout>
        <s:VerticalLayout horizontalAlign="left"
                          gap="10"/>
    </s:layout>
    <mx:DataGrid id="dg"
                 width="400"
                 height="250">
        <mx:columns>
            <mx:DataGridColumn headerText="Name"
                               dataField="name"/>
            <mx:DataGridColumn headerText="Surname"
                               dataField="surname"/>
            <mx:DataGridColumn headerText="Details"
                               textAlign="center"
                               width="100"
                               itemRenderer="main.view.components.DgItemRenderer"/>
        </mx:columns>
    </mx:DataGrid>
</s:Group>

Itemrenderer DataGrid-a

<s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
                          xmlns:s="library://ns.adobe.com/flex/spark">

    <s:CheckBox height="25"
                horizontalCenter="0"/>
</s:MXDataGridItemRenderer>

Mediator

public class PersonsListMediator extends FlexMediator
{
        /**
         * Mediator name
         */
        public static const NAME:String = "PersonsListMediator";

        public function PersonsListMediator(viewComponent:PersonsList)
        {
            super(NAME, viewComponent);
        }
        /**
         * Component
         */
        public function get personsList():PersonsList
        {
            return viewComponent as PersonsList;
        }
}

Mając do dyspozycji klasę mediatora możemy rejestrować Reakcje dla zdarzeń kontenera Group oraz wszystkich kontrolek które zawiera.

Jednak rejestracja Reakcji dla CheckBox-a znajdującego się w kolumnie DataGrid-a wymaga nieco więcej "gimnastyki". By mediator "wiedział" o zajściu zdarzenia w itemrenderer należy stworzyć własny even-t w kontrolce przypisanej do mediatora.

<fx:Metadata>
        /**
         *  Declare item renderer events
         */
        [Event(name="selectedChanged", type="flash.events.Event")]
</fx:Metadata>

Następnie etap to powiadomienie komponentu mediatora, że w itemrender zaszło zdarzenie "change" CheckBox-a.
Cały "trick" plega na uruchomieniu zdarzenia "selectedChanged" z włączonym tzw. bąbelkowaniem. Dzięki temu metoda obsługująca zdarzenie "selectedChanged" zostaje wykonana i osiągamy swój cel główny.


<s:MXDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
                          xmlns:s="library://ns.adobe.com/flex/spark">

    <s:CheckBox height="25"
                horizontalCenter="0"
                change="onChangeCheckBox(event)"/>
    <fx:Script>
        <![CDATA[
        /***
         * Create event with bubbles and dispatch it
         *
         * @param Event event
         */
        private function onChangeCheckBox(event:Event):void
        {
            dispatchEvent(new Event("selectedChanged", true));
        }
       ]]>
    </fx:Script>
</s:MXDataGridItemRenderer>

W mediatorze rejestracja reakcji dla zdarzenia "selectedChange" czyli "change" CheckBox-a odbywa się poprzez utworzenie metody zgodnie z zaleceniami na stronie projektu.

public function reactToPersonsList$SelectedChanged(event:Event):void
{
     Alert.show("selectedChange event");
}

Zaprezentowany powyżej przykład współpracy Reakcji i itemrenderer-ów został także przeze mnie opisany na stronie projektu, gdzie udostępniłem nieco obszerniejszy kod przykładu oraz możliwość jego uruchomienia – Zapraszam. :)