我正在努力找出在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
同时包含'data'和'label'字段(根据ComboBox
- 为什么它本身不提供labelField和idField,我永远不会知道)。
无论如何,上述MXML代码在两个方面不起作用:
那么,有没有人有类似的情况在工作?
答案 0 :(得分:5)
虽然杰夫的答案是对此方法的部分答案(请参阅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中查找Name),否则只在字段未被编辑时才能看到网格中的键(如果您的键/值相同,则不成问题。)
请注意,就我而言,我希望项目焦点事件能够传播给用户提供即时反馈(我的DataGrid有itemFocusOut="handleChange()"
),因此change
事件会创建ITEM_FOCUS_OUT事件。
请注意,当您不介意仅在用户单击要编辑的单元格时显示的ComboBox时,可能有更简单的方法将ComboBox作为ItemEditor。我想要的方法是在DataGrid中显示所有行的组合框,并且可编辑且具有良好的事件传播的通用方法。
答案 1 :(得分:2)
将itemRenderers添加到DataGrids的最简单方法是制作自定义MXML组件。在你的情况下,将canvas,HBox或VBox作为自定义组件,并将组合框作为子项添加。将dataProvider放在dataGrid本身上,并将itemRenderer分配给列,然后覆盖itemRenderer的set数据函数以进行访问来自该实例的给定数据提供者的所有数据,如下所示:
<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的每个实例调用此方法
答案 2 :(得分:1)
在我的例子中,我使用了一个spark datagrid,其中一列有一个使用DropDownListBox的ItemRenderer。我的问题是,当我的项目列表更改时,DropDownLists不会使用新的dataProvider进行更新。为了解决这个问题,我必须将DropDownListBox的dataProvider作为数据(ItemRenderer)的一部分传递,然后通过覆盖数据的setter来分配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"/>