Imagine a seguinte situação: você tem uma lista de um determinado objeto e cada objeto dessa lista tem uma propriedade. Essa propriedade é uma lista de um determinado objeto e você precisa popular um Repeater.
Vamos dar nomes aos objetos: suponha que você tenha uma lista de professores e cada professor tem seus alunos, bem, alguns irão dizer que é fácil, cada vez que o Repeater fizer um ItemDataBound basta fazer um busca novamente no banco de dados e listar o resultado. Como sempre me deparo com essa situação e vira e mexe algum me pergunta se essa é a melhor maneira de fazer resolvi escrever um artigo.
É muito simples, se a sua coleção já vem populada, basta você passar essa lista de objetos para o outro controle dentro do seu Repater (nesse caso outro Repeater), e isso será feito a cada ItemDataBound.
Classes
Temos as seguintes classes:
/// <summary> /// Classe mãe /// </summary> public abstract class Pessoa { private string _nome = string.Empty; public string Nome { get { return _nome; } set { _nome = value; } } public Pessoa() { } } /// <summary> /// Professor implementa Pessoa /// </summary> public class Professor : Pessoa { private string _materia = string.Empty; public string Materia { get { return _materia; } set { _materia = value; } } /// <summary> /// Um professor tem uma lista de alunos /// </summary> private System.Collections.Generic.List<Aluno> alunos = new System.Collections.Generic.List<Aluno>(); public System.Collections.Generic.List<Aluno> Alunos { get { return alunos; } set { alunos = value; } } public Professor(string nome, string materia, System.Collections.Generic.List<Aluno> alunos) { Nome = nome; Materia = materia; Alunos = alunos; } } /// <summary> /// Aluno implementa Pessoa /// </summary> public class Aluno : Pessoa { private string _turma = string.Empty; public string Turma { get { return _turma; } set { _turma = value; } } public Aluno(string nome, string turma) { Nome = nome; Turma = turma; } }
WebForm
Agora que já conhecemos nossas classes vamos para a implementação disso em uma página. Primeiro vamos criar um Repeater na página e, dentro dele, criaremos um segundo repeater, como no exemplo abaixo:
<asp:Repeater ID="ProfessorRepeater" runat="server" OnItemDataBound="ProfessorRepeater_ItemDataBound"> <ItemTemplate> Professor: <%# Eval("Nome") %> <br /> Matéria: <%# Eval("Materia") %> <br /> Alunos: <asp:Repeater ID="AlunoRepeater" runat="server"> <HeaderTemplate> <table> <tr style="font-weight: bold"> <td> Nome</td> <td> Curso</td> </tr> </HeaderTemplate> <FooterTemplate> </table> </FooterTemplate> <ItemTemplate> <tr style="background-color: Gray"> <td> <%# Eval("Nome") %> </td> <td> <%# Eval("Turma")%> </td> </tr> </ItemTemplate> <AlternatingItemTemplate> <tr style="background-color: Silver"> <td> <%# Eval("Nome") %> </td> <td> <%# Eval("Turma") %> </td> </tr> </AlternatingItemTemplate> </asp:Repeater> </ItemTemplate> <SeparatorTemplate> <hr /> </SeparatorTemplate> </asp:Repeater>
Atente para o detalhe que o repeater AlunoRepater está escrevendo as propriedades Nome (que vem de Pessoa) e turma (que é da classe Aluno).
Bom, mas isso não irá funcionar dessa maneira. Vejamos no code behind da página como é a implementação disso.
Code Behind
No PageLoad os objetos são criados e populados.
protected void Page_Load(object sender, EventArgs e) { Page.Title = "Repeater dentro de Repeater (DataList dentro de DataLista ou GridView dentro de GridView)"; // lista de alunos que será atribuída aos professores List<Aluno> alunosEpaminondas = new List<Aluno>(); alunosEpaminondas.Add(new Aluno("Alan", "Sistemas da Informação")); alunosEpaminondas.Add(new Aluno("Fabio", "Ciência da Computação")); alunosEpaminondas.Add(new Aluno("Marcelo", "Desenvolvimento de Sistemas Web")); // Só para não falar que os professores tem os mesmos alunos List<Aluno> alunosAdolfo = new List<Aluno>(); alunosAdolfo.Clear(); alunosAdolfo.Add(new Aluno("Carol", "Análise de Sistemas")); alunosAdolfo.Add(new Aluno("Bruno", "Banco de Dados")); // lista de professores List<Professor> professores = new List<Professor>(); professores.Add(new Professor("Epaminondas", "Gestão de Projetos", alunosEpaminondas)); professores.Add(new Professor("Adolfo", "Programação Orientação a Objetos", alunosAdolfo)); ProfessorRepeater.DataSource = professores; // define o DataSource do repeater como a lista de objetos professores ProfessorRepeater.DataBind(); }
No controle ProfessorRepeater, no evento ItemDataBound que o controle AlunoRepeater é populado, veja como é simples fazer a conversão do item do repeater que é passado.
protected void ProfessorRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e) { // verifica se o item é do tipo ItemType ou AlternatingItem, se não for retorna e não continua o processamento if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem) return; // verifica se o objeto AlunoRepeater existe dentro do item if (e.Item.Controls.Contains((Repeater)e.Item.FindControl("AlunoRepeater"))) { // cria um objeto Repeater e define-o como o objeto AlunoRepeater do item Repeater alunoRepeater = (Repeater)e.Item.FindControl("AlunoRepeater"); // converte o item (linha do repeater) para um professor e define a propriedade Alunos como DataSource do repeater alunoRepeater.DataSource = ((Professor)e.Item.DataItem).Alunos; alunoRepeater.DataBind(); } }
Super simples e tranqüilo, não há segredos nisso. A grande sacada é não ter que conectar ao banco novamente apenas obter os outros objetos. É possível utilizar isso também na criação de menus, para exibir a notas fiscais e seus itens, pedidos e seus itens etc. Aí vai depender da necessidade de cada projeto.
Até a próxima!