apache-flexcheckboxdatagridflex-spark

Spark datagrid with checkbox does not update correctly


The checkboxes are updated correctly when I select one or more datagrid rows but when I select a checkbox for the first time the checkbox does not refresh until the pointer moves out of the datagrid row. How can I fix this?

<?xml version="1.0" encoding="utf-8"?>
<s:Application 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:DataGrid id="dg" x="344" y="48" selectionMode="multipleRows" requestedRowCount="4">
        <s:columns>
            <s:ArrayList>
                <s:GridColumn>
                    <s:itemRenderer>
                        <fx:Component>
                            <s:GridItemRenderer>
                                <fx:Script>
                                    <![CDATA[
                                        import mx.controls.Alert;
                                        import spark.components.DataGrid;

                                        override public function prepare(hasBeenRecycled:Boolean):void
                                        {
                                            cb.selected = grid.selectionContainsIndex(rowIndex);
                                        }
                                    ]]>
                                </fx:Script>
                                <s:CheckBox id="cb" label="" horizontalCenter="0"/>
                            </s:GridItemRenderer>
                        </fx:Component>
                    </s:itemRenderer>
                </s:GridColumn>
                <s:GridColumn dataField="dataField1" headerText="Column 1"></s:GridColumn>
                <s:GridColumn dataField="dataField2" headerText="Column 2"></s:GridColumn>
                <s:GridColumn dataField="dataField3" headerText="Column 3"></s:GridColumn>
            </s:ArrayList>
        </s:columns>
        <s:typicalItem>
            <fx:Object dataField1="Sample Data" dataField2="Sample Data" dataField3="Sample Data"></fx:Object>
        </s:typicalItem>
        <s:ArrayList>
            <fx:Object dataField1="data1" dataField2="data1" dataField3="data1"></fx:Object>
            <fx:Object dataField1="data2" dataField2="data2" dataField3="data2"></fx:Object>
            <fx:Object dataField1="data3" dataField2="data3" dataField3="data3"></fx:Object>
            <fx:Object dataField1="data4" dataField2="data4" dataField3="data4"></fx:Object>
        </s:ArrayList>
    </s:DataGrid>
</s:Application>

Solution

  • You can just fake the CheckBox by drawing a CheckBox shape in the ItemRenderer and use the states to show the tick.

    <s:GridItemRenderer>
        <s:states>
            <s:State name="normal" />
            <s:State name="hovered" />
            <s:State name="selected" />
        </s:states>
    
        <!-- checkbox graphics -->
        <s:Group width="16" height="16" horizontalCenter="0" verticalCenter="0">
            <s:Rect left="0" right="0" top="0" bottom="0">
                <s:fill>
                    <s:SolidColor color="0xffffff" />
                </s:fill>
                <s:stroke>
                    <s:SolidColorStroke color="0xa9aeb2" />
                </s:stroke>
            </s:Rect>
    
            <!-- tick, only shown when selected -->
            <s:Rect includeIn="selected" width="8" height="8" horizontalCenter="0" verticalCenter="0">
                <s:fill>
                    <s:SolidColor color="0x90b40c" />
                </s:fill>
            </s:Rect>
        </s:Group>
    </s:GridItemRenderer>
    

    This is a simplified graphic for a checkbox, but you can go grab the code from the spark CheckBoxSkin and copy/paste it in the itemrenderer. Just might have to change some state names.

    This will not deselect a single row though when you hit the CheckBox of an already selected row, unless you hold the CTRL key down. That's the default behavior of the DataGrid component. I'm afraid you'll have to create your own subclass of DataGrid if you want to prevent that behavior.

    Another important thing to know: setting the selected property on the itemrenderers doesn't change the selectIndices of the DataGrid. Hence on the next commitProperties() cycle the value you set in the renderer will be overridden by the DataGrid.

    Old answer: (before edit)

    The ItemRenderer class (and thus the GridItemRenderer class too) has a selected property. So you could bind the checkboxes selected property to the itemrenders, like so:

    <s:CheckBox selected="{selected}" horizontalCenter="0" />
    

    You'd have to create a separate ItemRenderer class for that to work though instead of an inline one. If you absolutely want to go the inline way you can always override the selected setter.

    <s:GridItemRenderer>
      <fx:Script>
      <![CDATA[
          override public function set selected(value:Boolean):void {
              super.selected = cb.selected = value;
          }
      ]]>
      </fx:Script>
      <s:CheckBox id="cb" horizontalCenter="0"/>
    </s:GridItemRenderer>