ComboBox itemRendererを使用したFlex DataGrid
-
05-07-2019 - |
質問
"正しい" 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 Iの両方を提供しないのか決してわかりません)。
とにかく、上記のMXMLコードは2つの方法で機能しません:
- コンボボックスは、選択した項目とともに表示されません。
- アイテムを選択した後、選択したアイテムはデータストアに保存されません。
では、誰かが同様の状況で働いていますか?
解決
ジェフの答えは、このための1つのアプローチに対する部分的な答えですが( 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 =&quot; handleChange()&quot;
があるため) ITEM_FOCUS_OUTイベントを作成する change
イベント。
ComboBoxを編集するセルをクリックしたときにのみ表示されるComboBoxを気にしない場合、ComboBoxをItemEditorにする簡単な方法があることに注意してください。私が望んでいたアプローチは、すべての行のDataGridにコンボボックスを表示する一般的な方法であり、編集可能で適切なイベント伝播を備えていました。
他のヒント
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の各インスタンスに対して呼び出されます
私の場合、列の1つに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"/>