Desenvolvimento - C#
Repeater dentro de Repeater (DataList dentro de DataList ou GridView dentro de GridView)
Popular um Repeater com outro Repeater sem ter que acessar o banco novamente.
por Oscar CasagrandePessoal, imagine a seguinte situação, você tem uma lista de um determinado objeto e cada objeto dessa lista tem uma propriedade que é 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, 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 tranquilo, 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. bem, ai vai depender da necessidade de cada projeto.
Espero ter contribuído com esse artigo.