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:
O valor da propriedade da classe (que é uma instância de uma classe, no exemplo acima, uma instância da classe Endereco);
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:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
VB .NET - Paginação de dados no DataGridView com ... - Macoratti