Pergunta

Eu estou indo spare tentando descobrir a maneira "correta" para incorporar um ComboBox dentro de um Flex (3.4) DataGrid. Por direitos (por exemplo, de acordo com esta página http://blog.flexmonkeypatches.com/2008/02/18/simple-datagrid-combobox-as-item-editor-example/ ) deve ser fácil, mas eu não posso para a vida de mim fazer este trabalho.

A diferença que eu tenho que o exemplo ligada acima é que o meu valor de exibição (o que o usuário vê) é diferente para o valor id eu quero selecionar em e armazenar no meu provedor de dados.

Então, o que eu tenho é:

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

Onde transactionTypesData tem tanto 'Dados' e campos 'label'. (Conforme o que o ComboBox - porque na terra não oferece tanto um labelField e IDField eu nunca vou saber)

De qualquer forma, o código MXML acima não funcionar de duas maneiras:

  1. A caixa de combinação não aparecer com qualquer item selecionado.
  2. Depois de selecionar um item, ele não armazena costas que o item selecionado para o armazenamento de dados.

Então, se alguém tem um trabalho situação semelhante?

Foi útil?

Solução

Enquanto a resposta de Jeff é uma resposta parcial para uma abordagem para isso (ver http: // flex. gunua.com/?p=119 para um exemplo completo deste ser usado com bons resultados), não é tão geral como eu queria.

Felizmente, eu finalmente encontrei alguns grande ajuda no Experts Exchange (as respostas por hobbit72) descreve como criar um componente personalizado que funciona em uma grade como um ItemRenderer. Eu estendeu esse código para também suporta a utilização de caixa de combinação como um ItemEditor também. O componente completa é a seguinte:

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

Usando este componente é para a frente. Como um 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>

Usando este componente é para a frente. E como um 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>

Note que quando usá-lo como um ItemEditor, um labelFunction personalizado (que procura o nome do PersonID no meu caso) deve ser utilizado, caso contrário, você só vê a chave na grade quando o campo não está sendo editado ( não um problema se as chaves / valores são os mesmos).

Note que no meu caso, eu queria o foco item para fora evento para propagar-se para fornecer feedback imediato para o usuário (meu DataGrid tem itemFocusOut="handleChange()"), daí o evento change criar um evento ITEM_FOCUS_OUT.

Note que existem maneiras provavelmente mais simples ter uma caixa de combinação como um ItemEditor quando você não se importa a caixa de combinação única mostrado quando o usuário clica na célula para edição. A abordagem que eu queria era uma forma genérica para mostrar uma caixa de combinação em um DataGrid para todas as linhas, e sendo editável e com propogation evento decente.

Outras dicas

A maneira mais fácil de adicionar itemRenderers para DataGrids é fazer com que um componente MXML personalizado. No seu caso, fazer uma tela, HBox, ou VBox como o componente personalizado e adicionar a caixa de combinação como um child.Set o dataProvider no próprio dataGrid e atribuir o itemRenderer para a coluna e, em seguida, substituir a função de dados conjunto do itemRenderer para o acesso todos os dados do provedor de dados dada para essa instância como visto abaixo:

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

Este método será chamado para cada instância do itemRenderer

No meu caso eu usei um datagrid faísca, onde uma das colunas tem uma ItemRenderer que utiliza uma DropDownListBox. Meu problema era que quando a minha lista de itens de mudança, os DropDownLists não é atualizado com o novo dataProvider. Para resolver isso, eu tinha que passar o dataProvider para o DropDownListBox como parte dos dados (do ItemRenderer), e em seguida, substituindo o setter dos dados a apenas atribuir dataProvider do DropDownlListBox. Provavelmente um pouco de sobrecarga, mas se alguém tem uma solução melhor, por favor, deixe-me saber:

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top