9

我将不遗余力地试图找出在 Flex (3.4) DataGrid 中嵌入 ComboBox 的“正确”方法。按权利(例如根据此页面http://blog.flexmonkeypatches.com/2008/02/18/simple-datagrid-combobox-as-item-editor-example/)应该很容易,但我不能我的生活使这项工作。

我与上面链接的示例的不同之处在于我的显示值(用户看到的)与我想要选择并存储在我的数据提供程序中的 id 值不同。

所以我所拥有的是:

<mx:DataGridColumn headerText="Type" width="200" dataField="TransactionTypeID" editorDataField="value" textAlign="center" editable="true" rendererIsEditor="true">
    <mx:itemRenderer>
        <mx:Component>
            <mx:ComboBox dataProvider="{parentDocument.transactionTypesData}"/>
        </mx:Component>
    </mx:itemRenderer>
</mx:DataGridColumn>

哪里transactionTypesData有“数据”和“标签”字段(根据什么ComboBox- 为什么它不提供 labelField 和 idField 我永远不会知道)。

无论如何,上面的 MXML 代码不能以两种方式工作:

  1. 组合框不显示任何选定的项目。
  2. 选择项目后,它不会将该选定项目存储回数据存储区。

那么,有没有人遇到过类似的情况?

4

3 回答 3

5

虽然 Jeff 的回答是对此的一种方法的部分回答(请参阅http://flex.gunua.com/?p=119以获取此用于良好效果的完整示例),但它并不像我想要的那样普遍.

值得庆幸的是,我终于在Experts Exchange上找到了一些很大的帮助(hobbit72 的答案)描述了如何创建一个在网格中作为 ItemRenderer 工作的自定义组件。我已经将该代码扩展为也支持将组合框用作 ItemEditor。完整的组件如下:

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

使用这个组件很简单。作为 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>

使用这个组件很简单。作为一个 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>

请注意,当将其用作 ItemEditor 时,必须使用自定义 labelFunction(在我的情况下从 PersonID 查找名称),否则您只会在未编辑字段时在网格中看到键(不是问题如果您的键/值相同)。

请注意,在我的情况下,我希望将项目聚焦事件传播到向用户提供即时反馈(我的 DataGrid 有itemFocusOut="handleChange()"),因此该change事件创建了 ITEM_FOCUS_OUT 事件。

请注意,当您不介意仅在用户单击要编辑的单元格时显示 ComboBox 时,可能有更简单的方法可以将 ComboBox 作为 ItemEditor。我想要的方法是一种通用方法,可以在 DataGrid 中为所有行显示一个组合框,并且是可编辑的并且具有体面的事件传播。

于 2009-09-17T01:14:22.543 回答
2

将 itemRenderers 添加到 DataGrids 的最简单方法是制作自定义 MXML 组件。在您的情况下,将画布、HBox 或 VBox 作为自定义组件并将组合框添加为子项。在 dataGrid 本身上设置 dataProvider 并将 itemRenderer 分配给列,然后覆盖 itemRenderer 的设置数据功能以访问来自该实例的给定数据提供者的所有数据,如下所示:

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

将为 itemRenderer 的每个实例调用此方法

于 2009-09-14T18:30:14.633 回答
1

在我的例子中,我使用了一个 spark 数据网格,其中一个列有一个使用 DropDownListBox 的 ItemRenderer。我的问题是,当我的项目列表更改时,DropDownLists 不会使用新的 dataProvider 进行更新。为了解决这个问题,我必须将 DropDownListBox 的 dataProvider 作为数据(ItemRenderer)的一部分传递,然后通过覆盖数据的设置器来分配 DropDownlListBox 的 dataProvider。可能有点开销,但如果有人有更好的解决方案,请告诉我:

<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"/>

于 2014-02-02T13:16:22.763 回答