虽然 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 中为所有行显示一个组合框,并且是可编辑的并且具有体面的事件传播。