Question

Je vais essayer de trouver le "correct" manière d’intégrer une ComboBox dans un DataGrid Flex (3.4). Par droits (par exemple, selon cette page, http://blog.flexmonkeypatches.com/2008/02/18/simple-datagrid-combobox-as-item-editor-example/ ) ça devrait être facile, mais je ne peux pas pour la vie de moi faire ce travail.

La différence que j'ai par rapport à l'exemple ci-dessus est que ma valeur d'affichage (ce que voit l'utilisateur) est différente de la valeur id que je veux sélectionner et stocker dans mon fournisseur de données.

Donc, ce que j'ai est:

<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 contient à la fois les champs 'data' et 'label' (conformément à ce que le ComboBox - pourquoi ne fournit-il pas à la fois un labelField et un idField I ne saurai jamais).

Quoi qu'il en soit, le code MXML ci-dessus ne fonctionne pas de deux manières:

  1. La liste déroulante n'apparaît avec aucun élément sélectionné.
  2. Après avoir sélectionné un élément, il ne le stocke pas dans le magasin de données.

Alors, est-ce que quelqu'un a vécu une situation similaire?

Était-ce utile?

La solution

Tandis que la réponse de Jeff est une réponse partielle à une approche pour cette approche (voir http: // flex. gunua.com/?p=119 pour un exemple complet d'utilisation réussie), ce n'est pas aussi général que je le voulais.

Heureusement, j'ai finalement trouvé une aide précieuse sur Experts Exchange (les réponses par hobbit72) explique comment créer un composant personnalisé qui fonctionne dans une grille en tant que ItemRenderer. J'ai étendu ce code pour prendre également en charge l'utilisation de la zone de liste déroulante en tant qu'élément ItemEditor. Le composant complet est le suivant:

<?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'utilisation de ce composant est simple. En tant que 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'utilisation de ce composant est simple. Et comme 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>

Notez que lorsque vous l'utilisez en tant qu'EditEditor, vous devez utiliser une fonction labelFunction personnalisée (qui recherche le nom à partir du PersonID dans mon cas), sinon vous ne verrez la clé dans la grille que lorsque le champ n'est pas en cours de modification ( pas de problème si vos clés / valeurs sont les mêmes).

Notez que dans mon cas, je souhaitais que l'événement de focalisation sur éléments se propage pour fournir un retour immédiat à l'utilisateur (mon DataGrid a itemFocusOut = " handleChange () & <; code ), d'où la change événement créant un événement ITEM_FOCUS_OUT.

Notez qu'il existe probablement des moyens plus simples d'avoir une ComboBox en tant qu'EditEditor lorsque cela ne vous dérange pas que la ComboBox ne s'affiche que lorsque l'utilisateur clique sur la cellule à modifier. L’approche que je souhaitais était une méthode générique pour afficher une zone de liste déroulante dans un DataGrid pour toutes les lignes. Elle était modifiable et avec une propogation d’événement décente.

Autres conseils

La méthode la plus simple pour ajouter des éléments de rendu à DataGrids consiste à créer un composant MXML personnalisé. Dans votre cas, créez un canevas, une HBox ou une VBox en tant que composant personnalisé et ajoutez la combobox en tant qu'enfant. Définissez le fournisseur de données sur le composant DataGrid lui-même, affectez le paramètre itemRenderer à la colonne, puis remplacez la fonction de définition des données de l'élément itemRenderer pour y accéder. toutes les données du fournisseur de données indiqué pour cette instance, comme indiqué ci-dessous:

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

Cette méthode sera appelée pour chaque instance de itemRenderer

Dans mon cas, j’ai utilisé une grille de données spark dans laquelle l’une des colonnes avait un ItemRenderer qui utilisait un DropDownListBox. Mon problème était que lorsque ma liste d'éléments change, les listes DropDownLists ne sont pas mises à jour avec le nouveau fournisseur de données. Pour résoudre ce problème, je devais passer le fournisseur de données pour DropDownListBox dans les données (de ItemRenderer), puis redéfinir le configurateur des données pour n'affecter que le fournisseur de données de DropDownlListBox. Probablement un peu de frais généraux, mais si quelqu'un a une meilleure solution, s'il vous plaît laissez-moi savoir:

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

    

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top