Domanda

Vado di riserva cercando di capire il "corretto" modo per incorporare un ComboBox all'interno di un DataGrid Flex (3.4). Per diritti (ad es. Secondo questa pagina http://blog.flexmonkeypatches.com/2008/02/18/simple-datagrid-combobox-as-item-editor-example/ ) dovrebbe essere facile, ma non posso per la vita di me fare in modo che funzioni.

La differenza che ho nell'esempio sopra riportato è che il mio valore di visualizzazione (ciò che l'utente vede) è diverso dal valore ID che desidero selezionare e archiviare nel mio fornitore di dati.

Quindi quello che ho è:

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

Dove transactionTypesData ha sia i campi 'dati' che 'etichetta' (come per ciò che ComboBox - perché mai non fornisce sia un'etichettaField che idField I non lo saprò mai).

Comunque, il codice MXML sopra non funziona in due modi:

  1. La casella combinata non viene visualizzata con nessun elemento selezionato.
  2. Dopo aver selezionato un elemento, non lo memorizza nell'archivio dati.

Quindi, qualcuno ha una situazione simile al lavoro?

È stato utile?

Soluzione

Mentre la risposta di Jeff è una risposta parziale per un approccio per questo (vedi http: // flex. gunua.com/?p=119 per un esempio completo di come viene usato con buoni risultati), non è così generale come volevo.

Per fortuna, ho finalmente trovato un grande aiuto su Scambio di esperti (le risposte di hobbit72) descrive come creare un componente personalizzato che funzioni in una griglia come ItemRenderer. Ho esteso quel codice per supportare anche l'uso della casella combinata come ItemEditor. Il componente completo è il seguente:

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

L'uso di questo componente è semplice. Come 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>

L'uso di questo componente è semplice. E come 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>

Nota che quando lo usi come ItemEditor, nel mio caso deve essere usato un labelFunction personalizzato (che nel mio caso cerca il Nome dal PersonID), altrimenti vedi la chiave nella griglia solo quando il campo non viene modificato ( non è un problema se le tue chiavi / valori sono uguali).

Nota che, nel mio caso, volevo che l'evento focus out oggetto propellesse per fornire un feedback immediato all'utente (il mio DataGrid ha itemFocusOut = " handleChange () " ), quindi il change creando un evento ITEM_FOCUS_OUT.

Nota che ci sono probabilmente modi più semplici per avere un ComboBox come ItemEditor quando non ti dispiace che il ComboBox sia mostrato solo quando l'utente fa clic sulla cella per modificarlo. L'approccio che volevo era un modo generico per mostrare una casella combinata in un DataGrid per tutte le righe, ed essere modificabile e con una buona propagazione degli eventi.

Altri suggerimenti

Il modo più semplice per aggiungere itemRenderers a DataGrids è creare un componente MXML personalizzato. Nel tuo caso, crea un canvas, HBox o VBox come componente personalizzato e aggiungi la casella combinata come figlio. Imposta dataProvider su dataGrid stesso e assegna l'elemento Renderer alla colonna, quindi sovrascrivi la funzione di impostazione dati dell'elementoRenderer per accedere tutti i dati del fornitore di dati fornito per quell'istanza come indicato di seguito:

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

Questo metodo verrà chiamato per ogni istanza di itemRenderer

Nel mio caso ho usato un datagrid spark in cui una delle colonne ha un ItemRenderer che utilizza un DropDownListBox. Il mio problema era che quando il mio elenco di articoli cambia, DropDownLists non viene aggiornato con il nuovo dataProvider. Per risolvere questo, ho dovuto passare il dataProvider per DropDownListBox come parte dei dati (di ItemRenderer), e quindi sovrascrivendo il setter dei dati per assegnare semplicemente il dataProvider del DropDownlListBox. Probabilmente un po 'di spese generali, ma se qualcuno ha una soluzione migliore, per favore fatemi sapere:

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

    

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top