Dev (Back & Front)ARTIGO

Repeater dentro de Repeater (DataList dentro de DataList ou GridView dentro de GridView)

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><br />/// Classe mãe<br />/// </summary><br />public abstract class Pessoa<br />{<br />private string _nome = string.Empty;<br />public string Nome<br />{<br />get { return _nome; }<br />set { _nome = value; }<br />}<br />public Pessoa() { }<br />}<br />/// <summary><br />/// Professor implementa Pessoa<br />/// </summary><br />public class Professor : Pessoa<br />{<br />private string _materia = string.Empty;<br />public string Materia<br />{<br />get { return _materia; }<br />set { _materia = value; }<br />}<br />/// <summary><br />/// Um professor tem uma lista de alunos<br />/// </summary><br />private System.Collections.Generic.List<Aluno> alunos = new System.Collections.Generic.List<Aluno>();<br />public System.Collections.Generic.List<Aluno> Alunos<br />{<br />get { return alunos; }<br />set { alunos = value; }<br />}<br />public Professor(string nome, string materia, System.Collections.Generic.List<Aluno> alunos)<br />{<br />Nome = nome;<br />Materia = materia;<br />Alunos = alunos;<br />}<br />}<br />/// <summary><br />/// Aluno implementa Pessoa<br />/// </summary><br />public class Aluno : Pessoa<br />{<br />private string _turma = string.Empty;<br />public string Turma<br />{<br />get { return _turma; }<br />set { _turma = value; }<br />}<br />public Aluno(string nome, string turma)<br />{<br />Nome = nome;<br />Turma = turma;<br />}<br />}

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"><br /><ItemTemplate><br /><br />Professor:<br /><%# Eval("Nome") %><br /><br /><br /><br />Matéria:<br /><%# Eval("Materia") %><br /><br /><br /><br />Alunos:<br /><asp:Repeater ID="AlunoRepeater" runat="server"><br /><HeaderTemplate><br /><table><br /><tr style="font-weight: bold"><br /><td><br />Nome</td><br /><br /><td><br />Curso</td><br /></tr><br /><br /></HeaderTemplate><br /><FooterTemplate><br /></table><br /></FooterTemplate><br /><ItemTemplate><br /><tr style="background-color: Gray"><br /><td><br /><%# Eval("Nome") %><br /></td><br /><td><br /><%# Eval("Turma")%><br /></td><br /></tr><br /></ItemTemplate><br /><AlternatingItemTemplate><br /><tr style="background-color: Silver"><br /><td><br /><%# Eval("Nome") %><br /></td><br /><td><br /><%# Eval("Turma") %><br /></td><br /></tr><br /></AlternatingItemTemplate><br /></asp:Repeater><br /></ItemTemplate><br /><SeparatorTemplate><br /><hr /><br /></SeparatorTemplate><br /></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)<br />{<br />Page.Title = "Repeater dentro de Repeater (DataList dentro de DataLista ou GridView dentro de GridView)";<br />// lista de alunos que será atribuída aos professores<br />List<Aluno> alunosEpaminondas = new List<Aluno>();<br />alunosEpaminondas.Add(new Aluno("Alan", "Sistemas da Informação"));<br />alunosEpaminondas.Add(new Aluno("Fabio", "Ciência da Computação"));<br />alunosEpaminondas.Add(new Aluno("Marcelo", "Desenvolvimento de Sistemas Web"));<br />// Só para não falar que os professores tem os mesmos alunos<br />List<Aluno> alunosAdolfo = new List<Aluno>();<br />alunosAdolfo.Clear();<br />alunosAdolfo.Add(new Aluno("Carol", "Análise de Sistemas"));<br />alunosAdolfo.Add(new Aluno("Bruno", "Banco de Dados"));<br />// lista de professores<br />List<Professor> professores = new List<Professor>();<br />professores.Add(new Professor("Epaminondas", "Gestão de Projetos", alunosEpaminondas));<br />professores.Add(new Professor("Adolfo", "Programação Orientação a Objetos", alunosAdolfo));<br />ProfessorRepeater.DataSource = professores; // define o DataSource do repeater como a lista de objetos professores<br />ProfessorRepeater.DataBind();<br />}

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)<br />{<br />// verifica se o item é do tipo ItemType ou AlternatingItem, se não for retorna e não continua o processamento<br />if (e.Item.ItemType != ListItemType.Item && e.Item.ItemType != ListItemType.AlternatingItem) return;<br />// verifica se o objeto AlunoRepeater existe dentro do item<br />if (e.Item.Controls.Contains((Repeater)e.Item.FindControl("AlunoRepeater")))<br />{<br />// cria um objeto Repeater e define-o como o objeto AlunoRepeater do item<br />Repeater alunoRepeater = (Repeater)e.Item.FindControl("AlunoRepeater");<br />// converte o item (linha do repeater) para um professor e define a propriedade Alunos como DataSource do repeater<br />alunoRepeater.DataSource = ((Professor)e.Item.DataItem).Alunos;<br />alunoRepeater.DataBind();<br />}<br />}

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!

é técnico em Processamento de Dados pelo Colégio Técnico Elevação, tecnólogo em Desenvolvimento de Sistemas para Web no Instituto Brasileiro de Tecnologia Avançado (IBTA, agora Instituto Veris) e faz pós-graduação em Engenharia de Sistemas com ênfase em SOA, no Instituto Veris.

Ver perfil