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 Casagrande



Pessoal, 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.

Oscar Casagrande

Oscar Casagrande - 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 fazendo pós-graduação em Engenharia de Sistemas com ênfase em SOA no Instituto Veris.
Blog:
http://oscarcasagrande.blogspot.com.