Relacionamentos 1x1 na DataGrid

8 views
Skip to first unread message

Daniel Schmitz

unread,
Sep 20, 2008, 11:07:42 AM9/20/08
to fle...@googlegroups.com
Olá Pessoal,

É o seguinte, eu tenho uma classe chamada Pessoa, e outra chamada Endereco. Em Pessoa eu tenho uma propriedade chamada EnderecoResidencial que é do tipo Endereco.

Em um datagrid, quando eu estou criando uma coluna, eu não posso fazer assim não ?

<mx:AdvancedDataGridColumn headerText="Rua" dataField="EnderecoResidencial.Numero"/>




Luis Eduardo

unread,
Sep 20, 2008, 12:05:25 PM9/20/08
to fle...@googlegroups.com


Oi Daniel,

Com o componente AdvancedDataGrid eu não tenho certeza, mas o DataGrid
normal eu sei que isso é impossível, ao menos do jeito que ele é
"vendido".
Pra poder ter essa habilidade (eu tb precisei em um projeto) extendi o
datagridcolumn e usei um parser de xml feito pelo Michael Labriola. Na
extensão do DataGridColumn já tem um labelFuncton setado com a função
que chama o parser. Segue um rascunho da classe extendida:

<?xml version="1.0" encoding="utf-8"?>
<mx:DataGridColumn
xmlns:mx="http://www.adobe.com/2006/mxml"
labelFunction="displayXMLData"
>

<mx:Script>
<![CDATA[

public function displayXMLData( row:Object,
column:br.com.suprasis.Components.DataGridColumn ):String {
var retVal:String = E4XParser.evaluate( row, column.dataField );
return retVal;
}

]]></mx:Script>
</mx:DataGridColumn>

o codigo ficou meio estranho mas é pq retirei um tanto de coisas pra ficar
mais claro.

e aqui vai a Classe E4XParser, que aliás foi criada pelo Michael Labriola
e está disponível pra uso desde que mantenham-se os créditos.

espero que ajude, caso realmente o AdvancedDataGrid não tenha a
funcionalidade que vc precisa escondida em algum lugar.

abraços,
Luís Eduardo

E4XParser.as
-----------------
/*
* Copyright (c) 2006 Michael Labriola <labr...@digitalprimates.net>
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

/* This utility covers the major cases presented while parsing an e4x string.
* It is not complete, and, in particular is lacking in advanvced
predicate filtering.
* It also still needs support for regular expressions in the predicate
*/

package br.com.suprasis.Utils
{
import flash.utils.Dictionary;
import mx.utils.StringUtil;

public class E4XParser
{
static protected var patterns:Dictionary = new Dictionary(false);

static protected function sEqual( leftSide:String, rightSide:String
):Boolean {
return ( StringUtil.trim( leftSide ) == StringUtil.trim( rightSide ) );
}

static protected function sNotEqual( leftSide:String, rightSide:String
):Boolean {
return ( StringUtil.trim( leftSide ) != StringUtil.trim( rightSide ) );
}

static protected function sGreaterThan( leftSide:String,
rightSide:String ):Boolean {
return ( StringUtil.trim( leftSide ) > StringUtil.trim( rightSide ) );
}

static protected function sLessThan( leftSide:String, rightSide:String
):Boolean {
return ( StringUtil.trim( leftSide ) < StringUtil.trim( rightSide ) );
}

static protected function nEqual( leftSide:String, rightSide:String
):Boolean {
if ( isNaN( Number( leftSide ) ) || isNaN( Number( rightSide ) ) ) {
return sEqual( leftSide, rightSide );
}

return ( Number( leftSide ) == Number( rightSide ) );
}

static protected function nNotEqual( leftSide:String, rightSide:String
):Boolean {
if ( isNaN( Number( leftSide ) ) || isNaN( Number( rightSide ) ) ) {
return sNotEqual( leftSide, rightSide );
}

return ( Number( leftSide ) != Number( rightSide ) );
}

static protected function nGreaterThan( leftSide:String,
rightSide:String ):Boolean {
if ( isNaN( Number( leftSide ) ) || isNaN( Number( rightSide ) ) ) {
return sGreaterThan( leftSide, rightSide );
}

return ( Number( leftSide ) > Number( rightSide ) );
}

static protected function nLessThan( leftSide:String, rightSide:String
):Boolean {
if ( isNaN( Number( leftSide ) ) || isNaN( Number( rightSide ) ) ) {
return sLessThan( leftSide, rightSide );
}

return ( Number( leftSide ) < Number( rightSide ) );
}

static protected var comparisonMap:Object;
static protected function getComparisonHashMap():Object {
if ( !comparisonMap )
{
comparisonMap = new Object();
comparisonMap[ 'string' ] = new Object();
comparisonMap[ 'numeric' ] = new Object();

comparisonMap[ 'string' ][ '==' ] = sEqual;
comparisonMap[ 'string' ][ '!=' ] = sNotEqual;
comparisonMap[ 'string' ][ '>' ] = sGreaterThan;
comparisonMap[ 'string' ][ '<' ] = sLessThan;

comparisonMap[ 'numeric' ][ '==' ] = nEqual;
comparisonMap[ 'numeric' ][ '!=' ] = nNotEqual;
comparisonMap[ 'numeric' ][ '>' ] = nGreaterThan;
comparisonMap[ 'numeric' ][ '<' ] = nLessThan;
}

return comparisonMap;
}

static public var quotedAttrib:RegExp = /(@)\["*(\w+)"*\]/g;
static public var quotedBrackets:RegExp = /\["*(\w+)"*\]/g;
static public var brackets:RegExp = /\[(.+)\]/g;
static public var descendant:RegExp = /\.\./g;
static public var quotes:RegExp = /\"/g;
static public var periods:RegExp = /\./g;
static public var dotsInPredicate:RegExp = /(\([^\)]+)(\.)([^\)\.]+\))/g;
static public var previousDots:RegExp = /(.+)(\(dot\))(\.)/g;

static public function comparison( data:XMLList, comparison:String
):XMLList {
var operands:Array;
var returnList:XMLList = new XMLList();
var comparisonType:String;
var operator:String;

//Loose the parens
comparison = comparison.substr( 1, comparison.length - 2);

//Right now we are just supporting these four basic operators
//Feel free to add more for <=, >=, etc.
if ( comparison.search( "==" ) > -1 ) {
operator = "==";
} else if ( comparison.search( "!=" ) > -1 ) {
operator = "!=";
} else if ( comparison.search( ">" ) > -1 ) {
operator = ">";
} else if ( comparison.search( "<" ) > -1 ) {
operator = "<";
} else
throw new Error("Unknown Operator");

operands = comparison.split( operator );

var leftSide:String = operands[0];
var rightSide:String = operands[1];

if ( ( !leftSide.length ) || ( !rightSide.length ) )
throw new Error("Missing operand in comparison " + comparison );

//Does the right side have quotes?
if ( rightSide.substr(0,1) == '"' ) {
//Loose the quotes and do a string comparison
rightSide = rightSide.substr( 1, rightSide.length - 2);
comparisonType = "string";
} else {
//This means we are going to try the numeric test first,
//however, we still might not be able to convert the criterion
//to a number, in which case, we still revert to string
comparisonType = "numeric";
}

var compareFunction:Object = getComparisonHashMap();

var item:XML;
for ( var i:int=0; i<data.length(); i++ ) {
item = data[i];
//trace( "compare : " + item[ leftSide ] + " with " + rightSide );

if ( compareFunction[comparisonType][operator](
item[StringUtil.trim(leftSide)], rightSide ) )
{
returnList += item;
}
}

return returnList;
}

static public function descend( data:XMLList, expression:String ):XMLList {
//loose the double underscores
expression = expression.substr( 2 );

data = data.descendants( expression );

return data;
}

static public function evaluate( data:Object, expression:String ):XMLList {

var items:Array;

if ( !patterns[ expression ] )
{
//In our particular application this code is used within datagrids, so
the exact same
//pattern is searched many time. Basically, we are just optimizing for
this case by storing
//the split array of strings when we encounter the same pattern
var s:String = expression;

//Handle any quoted strings after the @ by removing the quotes and
brackets, not needed now
s = s.replace(quotedAttrib, "$1$2" );

//Handle any quoted strings inside of brackets and replace with a .
s = s.replace(quotedBrackets, ".$1" );

//Remove the remaining brackets and replace with a .
s = s.replace(brackets, ".$1" );

//We replace the descendant character with double underscores
s = s.replace( descendant, ".__" );

//This now gets extremely complicated. There are times when the
//predicate is very complicated, for instance, regular expressions
//right now we only support basic examples. Stay tuned for enhanced
versions
s = s.replace(dotsInPredicate, "$1(dot)$3" );

//We split the string along the remaining periods
items = s.split(periods);

for ( var j:int=0;j<items.length;j++ ) {
//We replace the phrase (dot) with real periods again as the split is
now complete
items[j] = items[j].replace(previousDots, "$1.$3" );
}

//Store this for the next round
patterns[ expression ] = items;
}
else
{
items = patterns[ expression ];
}

var dataPtr:Object;

var item:String;

dataPtr = data;
for ( var i:int = 0; i<items.length;i++ )
{
//items contains the expression, split apart to be examined
item = items[ i ];
if ( item.substr(0,1) == '(' ) {
//This is a prediate filter, now the fun work begins
dataPtr = comparison( XMLList( dataPtr ), item );
}
else if ( item.search( /__/ ) > -1 )
{
//this is a simple descendent case
dataPtr = descend( XMLList( dataPtr ), item );
}
else
{
if ( item.substr(0,1) == '"' ) {
//This handles the case where the user provides a quoted string to an
//array reference
item = item.replace(quotes, "");
}

//So long as the item exists, follow the pointer.
if ( item != '' )
dataPtr = dataPtr[ item ];
}
}

return XMLList( dataPtr );
}
}
}












-----------------------------
> dataField="*EnderecoResidencial.Numero*"/>
>
>
>
>
>
> >
>

Daniel Schmitz

unread,
Sep 20, 2008, 10:38:04 PM9/20/08
to fle...@googlegroups.com
Olá,

é não existe mesmo, uma pena :(

e vamu de labelFunction hehehe

Luis Eduardo escreveu:

Mário Júnior

unread,
Sep 22, 2008, 8:31:10 AM9/22/08
to fle...@googlegroups.com
Bem Daniel, realmente não pode fazer isso....  A solução seria por itemRenderer ou labelFunction. Já comentei sobre o uso de um (itemRenderer) ou outro (labelFunction) na lista flex-brasil, se quiser dar uma olhada leia aqui:

http://br.groups.yahoo.com/group/flex-brasil/message/12259

Então, a solução vc já sabe, mas melhor do saber a solução, é compreender do porquê vc não pode fazer como gostaria (Acessar objetos encapsulados diretamente na declaração do dataField) e eu já até expliquei em outro e-mail, mas por incrível q pareça a busca do gmail não encontrou... então vou dar uma pincelada "rápida" aqui na explicação, e como exemplo vou usar o <mx:DatagridColumn /> que é usado no <mx:Datagrid /> e tem implementação básica ao <mx: AdvancedDatagridColum />

##################
Este post pode se tornar comprido devido a explicação
###################

Veja só Daniel, abra o fonte da classe DataGridColumn.as (ctrl+click na tag), vá até a linha 1404 e encontrará um método (função) com o nome de itemToLabel(data : Object) que retorna uma String.

Agora, vendo sua implementação, atente-se para a linha 1419 onde ocorre-se isso:

....
data = data[dataField]
....

dataField é uma string e representa o nome da propriedade q vc informou lá no mxml, lembra? <mx:DatagridColumn dataField="Pessoa.Endereco" />

Perceba outra coisa interessante: o uso de acesso a atributos (propriedades do objeto) por meio de colchetes ( objeto["atributo"] )

Agora que já sabemos como uma propriedade é renderizada na coluna, vamos tentar visualizar a fonte do seu problema:

Tente visualizar o seguinte objeto:
var pessoa : Pessoa = new Pessoa();

pessoa.nome = "Mário"
pessoa.idade = 24
pessoa.contato.email = "con...@mariojunior.com"
pessoa.contato.blog = "blog.mariojunior.com"

Se vc escrever em uma coluna isso: <mx:DatagridColumn dataField="nome"/>
Internamente, o componente - para renderizar o atributo "nome" - fará isso lá na linha 1419:

....
data = data["nome"]; //data é o seu objeto atual, a "pessoa" em questão
....

Logo isso vai retornar o valor "Mário" corretamente naquela célula da coluna.


Agora, se vc fizer:
<mx:DatagridColumn dataField="contato.email"/>, internamente, o componente vai tentar fazer:
....
data = data["contato.email"];
....

E isso vai dar erro, pq não existe atributo "contato.email" ... oq existe é um atributo "contato" e dentro dele - encapsulado - existe outro atributo chamado "email"... logo, a maneira certa de acessar esse atributo é:

data = data["contato"]["email"] // Aqui sim, o resultado seria o esperado.

Mas como a implementação do componente não espera esse tipo de situação (objetos encapsulados), as maneiras de "contornar" essa situação é passar a responsabilidade para um itemRenderer ou um labelFunction, como vc fez.

Assim, eu espero q você - além de saber a solução - saiba também o motivo de ter recorrido a esses caminhos (labelFunction ou itemRenderer).


No mais, um forte abraço e desculpa o texto looooongo...


 
--
Mário de Souza Júnior
Programador Java / Adobe Flex
(44) 4009-3550 Maringá-PR
http://blog.mariojunior.com
junin...@gmail.com (gtalk, msn, etc..)

Daniel Negri

unread,
Sep 22, 2008, 11:22:02 AM9/22/08
to fle...@googlegroups.com

Eu tenho um exemplo pra trabalhar com “objetos encapsulados” em uma tabela. Não li todo o conteúdo da mensagem mas vê se esse código com labelFunction pode ajudar:

 

[Exemplo: TabelaNotaFiscalEletronica]

 

<?xml version="1.0" encoding="utf-8"?>

<mx:DataGrid xmlns:mx="http://www.adobe.com/2006/mxml" sortableColumns="false">

      <mx:Script>

            <![CDATA[

                  import mx.formatters.DateFormatter;

                  import br.com. empresa.negocio.nfe.TNFe;

                  import mx.utils.ObjectProxy;

                  import br.com.empresa.util.FormatadorNumerico;

                  import br.com. empresa.util.Converte;

                  import mx.collections.ArrayCollection;

                 

                  private function labelColunas(item:Object, column:DataGridColumn):String {                                         

                        var label:String = "";      

                        var formatadorNumerico:FormatadorNumerico = new FormatadorNumerico();           

                        var dateFormatter:DateFormatter = new DateFormatter();

                        dateFormatter.formatString = "DD/MM/YYYY";

 

                        var nfe:TNFe = item as TNFe;

 

                        try {                             

                             switch ( column ) {                                 

                                   case colNota :         

                                         label = String(nfe.infNFe.ide.NNF);

                                         break;     

                                        

                                   case colDataEmissao :

                                         label = dateFormatter.format(nfe.infNFe.ide.dataEmissao);         

                                         break;     

                                        

                                   case colDestinatario : 

                                         label = String(nfe.infNFe.dest.XNome);                                

                                         break;     

                                                                           

                                   case colCpfCnpjDestinatario :

                                         if ( nfe.infNFe.dest.cnpj != null && nfe.infNFe.dest.cnpj != "") {

                                               label = String(nfe.infNFe.dest.cnpj);         

                                         }

                                        

                                         if ( nfe.infNFe.dest.cpf != null && nfe.infNFe.dest.cpf != "") {

                                               label = String(nfe.infNFe.dest.cpf);          

                                         }

                                                                

                                         break;                 

                                        

                                   case colTipoEmissao :  

                                         if ( String(nfe.infNFe.ide.tpEmis) == "1")  {

                                               label =  "Normal";     

                                               break;

                                         }

                                        

                                         if ( String(nfe.infNFe.ide.tpEmis) == "2" ) {

                                               label =  "Contingência";    

                                               break;

                                         }

                                        

                                         if ( String(nfe.infNFe.ide.tpEmis) == "3" ) {

                                               label =  "SCAN"

                                               break;

                                         }

                                        

                                         break;           

                                                                                             

                                   case colSituacao :

                                         label = String(nfe.infNFe.ide.retorno.situacao);                                  

                                         break;

                                        

                                   case colDanfeImpresso :

                                         label = String(nfe.infNFe.ide.retorno.danfeImpresso);

                                         break;

                                  

                                   case colValor :        

                                         label = formatadorNumerico.format(Number(nfe.infNFe.total.icmsTot.vnf));                 

                                         break;     

                                                                                                         

                             }                            

                        } catch (e:Error) {

                             trace(e.message);

                        }

                       

                        if ( label == null || label == "null" ) {

                             label = "";

                        }

                       

                        return label;                     

                  }

            ]]>

      </mx:Script>

      <mx:columns>

            <mx:DataGridColumn id="colNota" headerText="Nota" labelFunction="labelColunas" width="90"/>

            <mx:DataGridColumn id="colDataEmissao" headerText="Data Emissão" labelFunction="labelColunas" width="90"/>

            <mx:DataGridColumn id="colDestinatario" headerText="Destinatario" labelFunction="labelColunas" minWidth="150"/>

            <mx:DataGridColumn id="colCpfCnpjDestinatario" headerText="CNPJ/CPF" labelFunction="labelColunas" width="120"/>                                 

            <mx:DataGridColumn id="colTipoEmissao" headerText="Tipo de Emissao" labelFunction="labelColunas" width="110"/>

            <mx:DataGridColumn id="colSituacao" headerText="Situação" labelFunction="labelColunas" width="90"/>           

            <mx:DataGridColumn id="colDanfeImpresso" headerText="Impresso" labelFunction="labelColunas" width="70"/>

            <mx:DataGridColumn id="colValor" headerText="Valor" labelFunction="labelColunas" width="90"/>

      </mx:columns>

</mx:DataGrid>

 

 

 

Percebeu que no meu objeto TNFe eu possuo vários objetos encapsulados?

TabelaNotaFiscal.mxml

Mário Júnior

unread,
Sep 22, 2008, 2:52:48 PM9/22/08
to fle...@googlegroups.com
Hum.... funciona bem Daniel (Negri) ... mas acho q assim vc amarra muito seu DataGrid.
Claro que, para todo caso vale análise antes, mas acho a coisa mais simples, viável, e - o mais importante - REUTILIZÁVEL  a se fazer nesse caso é:

1) extends DataGridColumn
2) sobrescreva o método itemToLabel (ele é public, logo pode ser sobrescrito)
3) faça um split(".") no dataField. Assuma o seguinte exemplo:

<renderers:DataGridColumn dataField="pessoa.contato.email" />


fazendo o split de "pessoa.contato.email" vc terá uma array com:
[0] = "pessoa"
[1] = "contato"
[2] = "email"

Com esse array em mãos, faça uma função recursiva (ou como alguns conhecem, "função de profundidade") que irá iterar em cada índice chamando a si própria e compor os atributos do seu objeto, passando dinamicamente a string como parâmetro para o nome do atributo a ser pesquisado.

No final, vc terá um resultado parecido com esse:

data["pessoa"]["contato"]["email"]

Assim seu dataGridColumn fica bem reaproveitável e com isso, os programadores q forem utilizar o seu componente, poderão usar "pessoa.contato.email" na declaração do dataField!

Q coisa linda de Deus... =D ...acho que vale até um post no blog
(meu blog anda mais parado q água de poço, capaz de conter larvas de dengue por lá =P)

Bem.. a idéia está aí... falta só a implementação.


Abraços.

Luis Eduardo

unread,
Sep 22, 2008, 4:49:54 PM9/22/08
to fle...@googlegroups.com


Mas é justamente isso que a classe E4XParser que eu mandei antes faz...
Com o bonus de tratar atributos de XML, coisa que vc não previu em seu
post.

pessoa.contato.@email

e o trem é free e codigo aberto. Refazê-lo é reinventar a roda, não?


abraços,
- Luís



> Hum.... funciona bem Daniel (Negri) ... mas acho q assim vc amarra muito
> seu
> DataGrid.
> Claro que, para todo caso vale análise antes, mas acho a coisa mais
> simples,
> viável, e - o mais importante - REUTILIZÁVEL a se fazer nesse caso é:
>
> 1) extends DataGridColumn
> 2) sobrescreva o método itemToLabel (ele é public, logo pode ser
> sobrescrito)
> 3) faça um split(".") no dataField. Assuma o seguinte exemplo:
>
> <renderers:DataGridColumn *dataField*="*pessoa.contato.email*" />

Mário Júnior

unread,
Sep 22, 2008, 5:06:05 PM9/22/08
to fle...@googlegroups.com
Sua solução é praticamente igual a do Daniel Negri.

Veja só bem:
- herança =! composição (embora ali há não há bem uma composição)
- sobreescrever o método itemToLabel =! criar método q será usado como labelFunction

Até poderia-se usar a classe E4XParser para recuperar os objetos, mas receio não haver necessidade pq penso que o parâmetro data (object) requerido pela função itemToLabel já foi parseado ao chegar ali.


Mas como eu disse, toda solução está sujeita a análise antes. Como um amigo diz: "não existe certo e errado, existe oq funciona bem e oq funciona mal, mas ambos funcionam" (quero deixar claro q discordo - um pouco - desse pensamento) =D


Um abraço.

Daniel Schmitz

unread,
Sep 22, 2008, 6:41:23 PM9/22/08
to fle...@googlegroups.com
Pessoal,

que bom tantas mensagens ! Eu acho que estou mau acostumado com o
XPO+ASPxGridView, que é uma outra tecnologia....

Deu pra ver que não dá mesmo,,,,.... tudo bem agente dá um jeito !!!! As
soluções que foram apresentadas resolvem o problema, e é isso que
importa !!!!!!!!!!!!!!!!

Abraços,
Daniel Pace Schmitz

Rodrigo Pereira Fraga

unread,
Sep 23, 2008, 7:05:26 AM9/23/08
to fle...@googlegroups.com
Apenas para complementar, em casos que estender a DataGrid não é viável, talvez a usar de métodos dentro dos próprios DTO's seja uma solução, como apresentado aqui:

http://forum.flexbrasil.com.br/viewtopic.php?f=8&t=455&p=1648&hilit=labelFunction#p1642

Utilizando o modo "decorado", é possível usar em qualquer outro componente, seja um List e etc...

Abraços,

2008/9/22 Daniel Schmitz <gro...@danielschmitz.net>



--
Atenciosamente:
-----------------------------------------------
| Rodrigo Pereira Fraga|
http://www.digows.com/
http://forum.flexbrasil.com.br/
-----------------------------------------------

Beck Novaes

unread,
Sep 23, 2008, 9:11:11 AM9/23/08
to flexdev
Isto aqui deve resolver também:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">

<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;

private function propChainLabelFunction(item:Object,
column:DataGridColumn):String
{
var currentItem:Object = item;
var chain:Array = column.dataField.split(".");
for each (var prop:String in chain)
{
currentItem = currentItem[prop];
}
return currentItem.toString();
}

]]>
</mx:Script>

<mx:ArrayCollection id="data">
<mx:Object>
<mx:col1>col1.1</mx:col1>
<mx:col2>
<mx:Object label="col1.2" data="1.2"/>
</mx:col2>
</mx:Object>
<mx:Object>
<mx:col1>col2.1</mx:col1>
<mx:col2>
<mx:Object label="col2.2" data="2.2"/>
</mx:col2>
</mx:Object>
<mx:Object>
<mx:col1>col3.1</mx:col1>
<mx:col2>
<mx:Object label="col3.2" data="3.2"/>
</mx:col2>
</mx:Object>
</mx:ArrayCollection>

<mx:DataGrid dataProvider="{data}">
<mx:columns>
<mx:DataGridColumn headerText="Col 1" dataField="col1"/>
<mx:DataGridColumn headerText="Col 2" dataField="col2.label"
labelFunction="propChainLabelFunction"/>
</mx:columns>
</mx:DataGrid>

</mx:Application>

Ou seja, onde você usar o "propChainLabelFunction" você poderá usar
"obj.prop" no dataField. Se você vai estender o DataGridColumn,
assinalar um labelFunction ou sobrescrever o itemToLabel... aí é com
você.

[]'s
Beck Novaes
> dataField="*EnderecoResidencial.Numero*"/>
Reply all
Reply to author
Forward
0 new messages