C# -  Exibindo objetos aninhados em um DataGridView


 Neste artigo eu vou mostrar como podemos exibir objetos aninhamos em um controle DataGridView.

O controle DataGridView é um daqueles controles versáteis que servem para exibir quase qualquer tipo de informação.

Mas e quando desejamos exibir propriedades de objetos que estão aninhadas ?  Ou seja, objetos que estão relacionados e que possuem propriedades dentro de outras propriedades ?

Um exemplo fácil de entender esse problema, e, que atende esse critério, é quando temos duas classes relacionadas, como por exemplo uma classe Cliente e uma classe Endereco contendo os endereços dos clientes.

    public class Cliente
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public string Email { get; set; }
        public Endereco Endereco { get; set; }
    }
    public class Endereco
    {
        public string Local { get; set; }
        public string Cidade { get; set; }
        public string Estado { get; set; }
    }

 

Classe Cliente Classe Endereco

Vamos seguir a abordagem tradicional e tentar exibir informações de clientes e seus endereços para ver o  que acontece.

Vamos criar uma solução usando o Visual Studio Community 2015 do tipo Windows Forms Application usando a linguagem C# com o nome Grid_Objetos.

Acionando o menu Project -> Add Class vamos criar as duas classes definidas acima : Cliente e Endereco.

No formulário form1.cs da solução criada vamos incluir um controle DataGridView com o nome gdvDados e um botão de comando (btnCarregar).

O formulário deve ficar assim:

Agora vamos incluir o código neste formulário para exibir algumas informações de clientes e endereços:

public partial class Form2 : Form
    {
        List<Cliente> listaClientes;
        public Form2()
        {
            InitializeComponent();
        }
        private void carregaListaClientes()
        {
            listaClientes = new List<Cliente>
            {
                new Cliente {  Id = 1, Nome = "Macoratti", Email = "macoratti@yahoo.com", Endereco = new Endereco { Local = "Rua Projetada, 100", Cidade = "Lins", Estado = "SP" } },
                new Cliente {  Id = 2, Nome = "Miriam Bueno", Email = "miriam@uol.com.br", Endereco = new Endereco { Local = "Av. Mexico, 10", Cidade = "Santos", Estado = "SP" } },
                new Cliente {  Id = 3, Nome = "Jefferson Lima", Email = "jefferson@hotmail.com", Endereco = new Endereco { Local = "Pça XV Novembro, 45", Cidade = "Campinas", Estado = "SP" } },
                new Cliente {  Id = 4, Nome = "Jessica Lang", Email = "jessicalang@uol.com.br", Endereco = new Endereco { Local = "Av. Mirassol, 234", Cidade = "São Paulo", Estado = "SP" } },
                new Cliente {  Id = 5, Nome = "Janice Silva", Email = "janjan@net.com.br", Endereco = new Endereco { Local = "Rua Equador , 21", Cidade = "Sorocaba", Estado = "SP" } }
            };
        }
        private void btnCarregar_Click(object sender, EventArgs e)
        {
            carregaListaClientes();
            dgvDados.DataSource = listaClientes;
            dgvDados.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
        }
    }

O código é bem simples:

Preenchemos os objetos Cliente e Endereco com informações a agora desejamos exibir no DataGridView as informações : Id, Nome, Email, Local, Cidade e Estado.

Veja o resultado obtido:

Não era o que desejávamos.

Vamos então definir cada coluna do GridView manualmente e ver se isso resolve.

Para isso selecione o DataGridView e na propriedade Columns abra a janela Edit Columns e clique no botão Add incluindo o nome e o texto a ser exibido em cada coluna :

A seguir para cada coluna defina a propriedade DataPropertyName, onde as propriedades do Endereco devem vir precedidas pelo nome classe Endereco mais o ponto e a seguir o nome da propriedade:

Executando o projeto novamente após esse ajuste teremos o seguinte resultado:

Ainda não conseguimos exibir todas as informações.

Resolvendo o problema

Vamos resolver esse problema usando uma abordagem bem simples que foi sugerida pelo colega Antonio Bello neste artigo : http://www.developer-corner.com/blog/2007/07/19/datagridview-how-to-bind-nested-objects/

Vamos usar o evento CellFormatting do DataGridView  para diferenciar se o campo a ser exibido é um tipo de dado da classe base ou um objeto que deseja expor suas próprias propriedades. Fazemos isso verificando se o campo que definimos na propriedade DataPropertyName do DataGridView possui o ponto (".").

Assim podemos identificar as propriedades Endereco.Local, Endereco.Cidade e Endereco.Estado. 

Veja como ficou o código definido no evento CellFormatting :

        private void dgvDados_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            if ((dgvDados.Rows[e.RowIndex].DataBoundItem != null) && (dgvDados.Columns[e.ColumnIndex].DataPropertyName.Contains(".")))
            {
                e.Value = BindProperty(dgvDados.Rows[e.RowIndex].DataBoundItem, dgvDados.Columns[e.ColumnIndex].DataPropertyName);
            }
        }

 

Observe que neste código após verificar se existe o ponto em DataPropertyName usamos o método BindProperty para resolver e exibir o valor da propriedade do objeto.

A seguir temos o código do método BindProperty:

        private string BindProperty(object property, string propertyName)
        {
            string retValue = "";
            if (propertyName.Contains("."))
            {
                PropertyInfo[] arrayProperties;
                string leftPropertyName;
                leftPropertyName = propertyName.Substring(0, propertyName.IndexOf("."));
                arrayProperties = property.GetType().GetProperties();
                foreach (PropertyInfo propertyInfo in arrayProperties)
                {
                    if (propertyInfo.Name == leftPropertyName)
                    {
                        retValue = BindProperty(
                          propertyInfo.GetValue(property, null),
                          propertyName.Substring(propertyName.IndexOf(".") + 1));
                        break;
                    }
                }
            }
            else
            {
                Type propertyType;
                PropertyInfo propertyInfo;
                propertyType = property.GetType();
                propertyInfo = propertyType.GetProperty(propertyName);
                retValue = propertyInfo.GetValue(property, null).ToString();
            }
            return retValue;
        }

O método BindProperty resolve o nome da propriedade dos dados e fornece o valor real a ser exibido na célula usando reflexão e recursão (se necessário).

Dois argumentos são passados para o método BindProperty:

  1. O valor da propriedade da classe (que é uma instância de uma classe, no exemplo acima, uma instância da classe Endereco);

  2. E o DataPropertyName;

Usamos Reflection para ler o valor da propriedade, obtida pela recuperação de PropertyInfo da variável propriedade, e em seguida, obtemos o valor da propriedade chamando o método GetValue() da instância PropertyInfo.

Assim a variável leftPropertyName contém o nome da propriedade mais à esquerda, por exemplo, se propertyName for Endereco.Local , ela é preenchido com o valor de Local do endereço.

Executando o projeto com essas implementações feitas teremos o seguinte resultado:

Agora podemos ver que estamos exibindo as informações do cliente e seus endereço no DataGridView.

Essa é apenas uma as muitas abordagens que podemos realizar para conseguir realizar essa tarefa.

Pegue o projeto completo aqui :   Grid_Objetos.zip

Pois, assim como o Pai ressuscita os mortos, e os vivifica, assim também o Filho vivifica aqueles que quer.
E também o Pai a ninguém julga, mas deu ao Filho todo o juízo;
Para que todos honrem o Filho, como honram o Pai. Quem não honra o Filho, não honra o Pai que o enviou.

João 5:21-23

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?


  Gostou
?   Compartilhe no Facebook   Compartilhe no Twitter

 

Referências:


José Carlos Macoratti