Flex DataGrid with ComboBox itemRenderer

后端 未结 3 797
轻奢々
轻奢々 2021-02-04 14:12

I\'m going spare trying to figure out the \"correct\" way to embed a ComboBox inside a Flex (3.4) DataGrid. By Rights (e.g. according to this page http://blog.flexmonkeypatches.

相关标签:
3条回答
  • 2021-02-04 14:16

    In my case I used a spark datagrid where one of the columns has an ItemRenderer that utilises a DropDownListBox. My problem was that when my item list change, the DropDownLists doesn't get updated with the new dataProvider. To solve this, I had to pass the dataProvider for the DropDownListBox as part of the data (of the ItemRenderer), and then by overriding the setter of the data to just assign the DropDownlListBox's dataProvider. Probably a bit of overhead, but if someone have a better solution, please let me know:

    <s:GridItemRenderer xmlns:fx="http://ns.adobe.com/mxml/2009" 
                    xmlns:s="library://ns.adobe.com/flex/spark" 
                    xmlns:mx="library://ns.adobe.com/flex/mx">
    <fx:Script>
        <![CDATA[
            override public function set data(v : Object) : void {
                super.data = v;
                if (v == null)
                    return;
                dropDown.dataProvider = data.dataProvider;
            }
        ]]>
    </fx:Script>
    <s:DropDownList id="dropDown" width="100%" height="100%" dataProvider="{data.dataProvider}" labelField="name"/>
    

    0 讨论(0)
  • 2021-02-04 14:24

    While Jeff's answer is a partial answer for one approach for this (see http://flex.gunua.com/?p=119 for a complete example of this being used to good effect), it isn't as general as I wanted.

    Thankfully, I finally found some great help on Experts Exchange (the answers by hobbit72) describes how to create a custom component that works in a grid as a ItemRenderer. I've extended that code to also support using the combo box as an ItemEditor as well. The full component is as follows:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:ComboBox
        xmlns:mx="http://www.adobe.com/2006/mxml" 
        dataChange="setSelected()" 
        change="onSelectionChange(event)"
        focusEnabled="true">
        <mx:Script>
            <![CDATA[
                import mx.events.DataGridEvent;
                import mx.events.ListEvent;
                import mx.controls.dataGridClasses.DataGridListData;
    
                private var _ownerData:Object;
                private var _lookupField:String = "value";
    
                // When using this component as an itemEditor rather than an itemRenderer
                // then set ' editorDataField="selectedItemKey"' on the column to 
                // ensure that changes to the ComboBox are propogated.
                [Bindable] public var selectedItemKey:Object;
    
                public function set lookupField (value:String) : void {
                    if(value) {
                        _lookupField = value;
                        setSelected();
                    }
                }           
                override public function set data (value:Object) : void {
                    if(value) {                    
                        _ownerData = value;
                        setSelected();
                    }
                }
                override public function get data() : Object {
                    return _ownerData;
                }            
                private function setSelected() : void {
                    if (dataProvider && _ownerData) {
                        var col:DataGridListData = DataGridListData(listData);
                        for each (var dp:Object in dataProvider) {
                            if (dp[_lookupField] == _ownerData[col.dataField]) {
                                selectedItem = dp;
                                selectedItemKey = _ownerData[col.dataField];
                                return;     
                            }
                        }                    
                    }
                    selectedItem = null;
                }
                private function onSelectionChange (e:ListEvent) : void {
                    if (selectedItem && _ownerData) {                    
                        var col:DataGridListData = DataGridListData(listData);
                        _ownerData[col.dataField] = selectedItem[_lookupField];
                        selectedItemKey = selectedItem[_lookupField];
                    }
                }                   
            ]]>
        </mx:Script>    
    </mx:ComboBox> 
    

    Using this component is straight forward. As an ItemRenderer:

    <mx:DataGridColumn headerText="Child" dataField="PersonID" editable="false" textAlign="center">
      <mx:itemRenderer>
        <mx:Component>
          <fx:GridComboBox dataProvider="{parentDocument.childrenData}" labelField="Name" lookupField="PersonID" change="dispatchEvent(new mx.events.DataGridEvent(mx.events.DataGridEvent.ITEM_FOCUS_OUT, true, true))"/>
        </mx:Component>
      </mx:itemRenderer>                      
    </mx:DataGridColumn>
    

    Using this component is straight forward. And as an ItemEditor:

    <mx:DataGridColumn labelFunction="lookupChildName" headerText="Child" dataField="PersonID" editable="true" editorDataField="selectedItemKey">
        <mx:itemEditor>
            <mx:Component>
                <fx:GridComboBox dataProvider="{parentDocument.childrenData}" labelField="Name" lookupField="PersonID" change="dispatchEvent(new mx.events.DataGridEvent(mx.events.DataGridEvent.ITEM_FOCUS_OUT, true, true))"/>
            </mx:Component>
         </mx:itemEditor>      
    </mx:DataGridColumn>
    

    Note that when using it as an ItemEditor, a custom labelFunction (that looks up the Name from the PersonID in my case) must be used, otherwise you only see the key in the grid when the field isn't being edited (not a problem if your keys/values are the same).

    Note that in my case, I wanted the item focus out event to propogate up to provide immediate feedback to the user (my DataGrid has itemFocusOut="handleChange()"), hence the change event creating an ITEM_FOCUS_OUT event.

    Note that there are probably simpler ways to have a ComboBox as an ItemEditor when you don't mind the ComboBox only shown when the user clicks on the cell to edit. The approach I wanted was a generic way to show a combo box in a DataGrid for all rows, and being editable and with decent event propogation.

    0 讨论(0)
  • 2021-02-04 14:41

    The easiest way to add itemRenderers to DataGrids is to make a custom MXML component. In your case make a canvas, HBox, or VBox as the custom component and add the combobox as a child.Set the dataProvider on the dataGrid itself and assign the itemRenderer to the column, and then override the set data function of the itemRenderer to access all data from the given data provider for that instance as seen below:

    <mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
    <mx:Script>
        <![CDATA[
    
            override public function set data(value:Object):void{
                        trace(value.data);
                        trace(value.name);
            }
        ]]>
       </mx:Script>
    
    <mx:ComboBox width="100%" height="100%" id="myComboBox"/>
     </mx:HBox>
    

    This method will be called for each instance of the itemRenderer

    0 讨论(0)
提交回复
热议问题