Search code examples
actionscript-3apache-flexevent-handlingflex4itemrenderer

Detecting CheckBox Selection in an ItemRenderer


I needed to display a list where each item consists of a checkbox followed by a label. To do this I created a custom itemrenderer class for the List. Creating and applying the renderer class was simple enough and everything displayed correctly. Now I need to add a function to the renderer class that will do something like changing the text color when the checkbox is selected or de-selected. I know that CheckBox has a 'change' event but when I try to listen for that event I run into a catch-22. I need to set the 'mouseChildren' property of the renderer class to false to prevent the mouse events of the List and the Checkbox from interfering with each other. Unfortunately, setting that property to false is also preventing the change event from the checkbox, so my handler never gets called. I'm completely stumped on this, any help would be greatly appreciated.

For reference, here is the code for my renderer class:

<?xml version="1.0" encoding="utf-8"?>
<s:ItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009"
                xmlns:s="library://ns.adobe.com/flex/spark"
                xmlns:mx="library://ns.adobe.com/flex/mx"
                autoDrawBackground="true"
                mouseChildren="false"
                width="100%">
    <s:states>
        <s:State name="normal"/>
        <s:State name="hovered"/>
        <s:State name="selected"/>
    </s:states>
    <s:HGroup left="10"
              right="0"
              top="0"
              bottom="0"
              verticalAlign="middle"
              gap="3">
        <s:CheckBox selected.selected="true"
                    change="{handleCBChange()}"/>
        <s:Label text="{data.value}"
                 width="100%"/>
    </s:HGroup>
    <fx:Script>
        <![CDATA[
            public function handleCBChange():void
            {
                trace("Checkbox clicked");
            }
        ]]>
    </fx:Script>
</s:ItemRenderer>

Solution

  • After banging my head against the while, I think I finally figured out the issue. The key is how I was binding selected.

    selected.selected="true"

    The purpose of that code is to make sure the checkbox gets toggled if the user clicks anywhere on the List Item (thus changing the renderer state). The trouble with that is that clicking on the actual checkbox ALSO causes the value of selected to change. So the state change was setting 'selected' to true and then the checkbox was responding to the click by setting it back to false. By setting 'mouseChildren' to false I was preventing the mouse event on the checkbox from retoggling the selection. Unfortunately it also suppresses the 'change' event I was trying to listen for.

    The good new is, I found a workaround. Instead of listening for the 'change' event of the checkbox I added a listener for the 'valueCommit' event instead. Since valueCommit gets fired by programmatic changes to 'selected', the selected.selected=true binding will trigger the event and let me respond to the change.