0
votes

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>
4

4 Answers

0
votes

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>
2
votes

Change this:

 <s:CheckBox id="cb" label="" horizontalCenter="0"/> 

To:

<s:CheckBox id="cb" label="" horizontalCenter="0" enabled="false"/>

I just recommend you to use enabled property.

I think the dispatched "click event" from both checkbox and gridColumn, then returned function prevented each other.

If enabled property set false, your click event dispathed on only gridColumn then using cb.selected=grid.selectionContainsIndex(rowIndex); correctly occupy if you want to show checkbox enabled, you can use CSS or skinclass

1
votes

The easiest way is to just use the renders selected state as suggested by RIAStar. However if you are using global skinning doing the custom drawing does not work, use either a skinnable container or as I have just put the checkbox in there but dont make it respond to mouse commands. For the multi selection, as long as your grid is setup to multiple rows or columns you can simply capture the mouse events and force the ctrl key which makes them handle multi select.

<s:GridItemRenderer 
    mouseDown="mouseDownHandler(event)"
    mouseUp="mouseUpHandler(event)"
    buttonMode="true"
    mouseChildren="false"
    useHandCursor="true"
    xmlns:fx="http://ns.adobe.com/mxml/2009"
    xmlns:mx="library://ns.adobe.com/flex/mx"
    xmlns:s="library://ns.adobe.com/flex/spark"
    >

    <s:states>
        <s:State name="normal"/>
        <s:State name="selected"/>
    </s:states>

    <fx:Script>
        <![CDATA[
            protected function mouseUpHandler(event:MouseEvent):void {
                event.ctrlKey = true;
            }

            protected function mouseDownHandler(event:MouseEvent):void {
                event.ctrlKey = true;
            }
        ]]>
    </fx:Script>

    <s:CheckBox 
        id="check"
        selected.normal="false"
        selected.selected="true"
        horizontalCenter="0"
        verticalCenter="0"
        />

</s:GridItemRenderer>
1
votes

I ended up simply doing this:

            <s:GridColumn dataField="myBoolean" headerText="Returned" width="55">
                <s:itemRenderer>
                    <fx:Component>
                        <s:GridItemRenderer>
                                <s:CheckBox id="cb1" selected="{data.myBoolean}" change="{data.myBoolean=cb1.selected}"/>                                                           
                        </s:GridItemRenderer>
                    </fx:Component>
                </s:itemRenderer>
            </s:GridColumn>