Search code examples
apache-flexflex4advanceddatagrid

Issues with Spark DropDownList as itemEditor within AdvancedDataGrid


I'm trying to use the Spark DropDownList as itemEditor in an AdvancedDataGrid. Howerver, I've stumbled onto two issues:

  1. Clicking on a item in the DropDownList changes the selected row in the ADG. You can see this behavior by compiling the code from below and executing the following steps.

    • Open the DropDownList by Clicking on "A" in Row 1
    • Select "C" with your mouse

    The value changes from "A" to "C" and Row 3 is the selected row in the ADG. It looks like the mouse click in the DropDownList is also handled by the ADG itself which changes the selected row accordingly. I couldn't figure out a way to prevent this. The expected behavior would be that row 1 is still selected after the DropDownList has been closed.

  2. Clicking on the scrollbar of the DropDownList closes the DropDownList. (I just found the solution to this problem in the relatated questions while writing this: Scrollbars in dropdownlist inside DataGrid itemEditor not working)

Application

<?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" minWidth="955" minHeight="600">

    <s:layout>
        <s:VerticalLayout horizontalAlign="center" verticalAlign="middle"/>
    </s:layout>

    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayCollection;

            [Bindable]
            private var myDataProvider:ArrayCollection = new ArrayCollection([
                {label: "Row 1", value: "A"},
                {label: "Row 2", value: "B"},
                {label: "Row 3", value: "C"},
                {label: "Row 4", value: "D"},
                ]);
        ]]>
    </fx:Script>

    <mx:AdvancedDataGrid dataProvider="{myDataProvider}" editable="true">
        <mx:columns>
            <mx:AdvancedDataGridColumn headerText="Label" dataField="label" width="150"/>
            <mx:AdvancedDataGridColumn headerText="Value" dataField="value" width="200" editorDataField="selectedItem"
                                       itemEditor="DropDownListEditor"/>
        </mx:columns>
    </mx:AdvancedDataGrid>
</s:Application>

ItemEditor

<?xml version="1.0" encoding="utf-8"?>
<s:MXAdvancedDataGridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
                                  xmlns:mx="library://ns.adobe.com/flex/mx" focusEnabled="true"
                                  implements="mx.managers.IFocusManagerComponent">

    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayList;
            import mx.collections.IList;

            [Bindable]
            public var values:IList = new ArrayList(["A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
                "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]);

            public function get selectedItem():*
            {
                return dropDownList.selectedItem;
            }

            public override function setFocus():void
            {
                dropDownList.setFocus();
            }
        ]]>
    </fx:Script>

    <s:DropDownList id="dropDownList" top="2" left="2" right="2" bottom="2" dataProvider="{values}"
                    selectedItem="{listData.label}" open="dropDownList.skin['dropDown'].owner = this"/>
</s:MXAdvancedDataGridItemRenderer>

Solution

  • Thanks to ed I've now found a solution that seems to work quite fine. The DropDownList uses the MOUSE_DOWN event to close the dropDown. So, the dropDown doesn't exist anymore when the MOUSE_UP event is fired. That is why the ADG receives the MOUSE_UP event and changes the selected row.

    I'm now using a custom DropDownList where I suppress the first MOUSE_UP event that follows after the dropDown has been closed. So far this works without problems.

    protected override function dropDownController_closeHandler(event:DropDownEvent):void
    {
        systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_UP, systemManager_mouseUpHandler, true);
        super.dropDownController_closeHandler(event);
    }
    
    protected function systemManager_mouseUpHandler(event:MouseEvent):void
    {
        systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_UP, systemManager_mouseUpHandler, true);
        event.stopImmediatePropagation();
    }