Scrollbars in dropdownlist inside DataGrid itemEdi

2019-01-26 22:04发布

问题:

I have a DropDownList inside the itemEditor of my DataGrid. There are enough items in the DropDownList to justify scrollbars. You can see the scrollbars, and the mousewheel works fine. If you move the mouse over the scrollbars, they'll change appearance fine (mouseover is working). If you click on them, the DropDownList closes as if you'd clicked elsewhere in the data grid.

There's a comment on the Adobe Forums that describe the same problem, but it is fairly old and has not been answered.

I've been experimenting with custom skins hoping to find a way to trap the mouse event, but have been unsuccessful.

FWIW, this is Flex4, as an AIR app.

Scratch.mxml (main code)

    <?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
        xmlns:s="library://ns.adobe.com/flex/spark" 
        xmlns:mx="library://ns.adobe.com/flex/mx"
        creationComplete="windowedapplication1_creationCompleteHandler(event)">
 <fx:Script>
  <![CDATA[
   import mx.collections.ArrayCollection;
   import mx.events.FlexEvent;
   [Bindable] public var dataList:ArrayCollection = new ArrayCollection();

   protected function windowedapplication1_creationCompleteHandler(event:FlexEvent):void
   {
    var o:Object = new Object();

    o.theChoice = "abc";
    o.choices = new ArrayCollection();
    o.choices.addItem("abc");
    o.choices.addItem("def");
    o.choices.addItem("ghi");
    o.choices.addItem("jkl");
    o.choices.addItem("mno");
    o.choices.addItem("pqr");
    o.choices.addItem("stu");
    o.choices.addItem("vwx");
    o.choices.addItem("yz ");
    dataList.addItem(o);
   }
   protected function col2Label(item:Object, column:DataGridColumn):String {
    return item.theChoice;
   }
   // If you use the labelFunction, then you must specify a sortCompareFunction
   private function sortCol2(obj1:Object, obj2:Object):int
   {
    var d1:String = obj1.col2 as String;
    var d2:String = obj2.col2 as String;
    if(d1 < d2) {
     return -1;
    } else if(d1 == d2) {
     return 0;
    }
    return 1;
   }

  ]]>
 </fx:Script>
 <fx:Declarations>
  <!-- Place non-visual elements (e.g., services, value objects) here -->
 </fx:Declarations>
 <mx:DataGrid id="glGrid" top="10" left="10" right="10" bottom="10"
     dataProvider="{dataList}" editable="true" >

  <mx:columns>
   <mx:DataGridColumn id="col2" 
          headerText="Column 2"  
          itemEditor="Renderers.ddlRenderer" 
          labelFunction="col2Label" 
          dataField="col2"
          sortCompareFunction="sortCol2"/>
  </mx:columns>  
 </mx:DataGrid>
</s:WindowedApplication>

ddlRenderer.mxml:

    <?xml version="1.0" encoding="utf-8"?>
<s:MXDataGridItemRenderer 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">
 <fx:Script>
  <![CDATA[
   import mx.collections.ArrayList;

   import spark.events.IndexChangeEvent;

   [Bindable] private var myChoices : ArrayList = new ArrayList();

   override public function set data(value:Object):void
   {
    if (value != null) {
     super.data = value;
     if (ddl && myChoices) {
      myChoices.removeAll();
      var theChoice:String = value.theChoice;

      myChoices.addAll(value.choices);

      var lineChoice : String;
      for (var i:int = 0; i < myChoices.length; i++) {
       lineChoice = myChoices.getItemAt(i) as String;
       if (lineChoice == theChoice) {
        ddl.selectedItem = lineChoice;
        break;
       }
      }
     }
    }
   }

  ]]>
 </fx:Script>

 <s:DropDownList id="ddl" 
     width="100%" 
     dataProvider="{myChoices}"/>
</s:MXDataGridItemRenderer>

To see the problem, run the code, click on "abc" to trigger the itemRenderer, click on the DropDownList to see the choices, then try clicking on the scrollbar.

I'm stumped on this one, and would greatly appreciate some help.

Thanks

Dan

回答1:

I posted this to Adobe as a bug (SDK-27783, Flex SDK, Spark:DropDownList), which was just closed today. Alex Harui had a good workaround:

Workaround is to change renderer as follows:

<s:DropDownList id="ddl" 
 width="100%" 
 dataProvider="{myChoices}" open="ddl.skin['dropDown'].owner = this"/>

I tested this and it solves my problem. Hopefully this will help others as well.



回答2:

I'm not sure that it's a mouseEvent that you should to trap. You can debug the framework class: DropDownController.as, put a breakpoint at the start of the systemManager_mouseDownHandler function and processFocusOut function. You can see when you clic on the dropdownlist'scrollbar that the systemManager_mouseDownHandler function doesn't call closeDropDown, closeDropDown is called by processFocusOut.

Now add a DropDownList object at the top of your application:

<s:DropDownList id="ddltop"
                    top="10"
                    left="10"
                    width="100%"
                    dataProvider="{dataList.getItemAt(0).choices}"
                    />
<mx:DataGrid id="glGrid" top="50" left="10" right="10" bottom="10"

...

and debug again with the same breakpoints. Now it's the systemManager_mouseDownHandler function that call closeDropDown.

Perhaps the reason for the closure of the dropdownlist.