Desenvolvimento - ASP. NET

WPF ListBox: Customizando a exibição de dados

Veja neste artigo como customizar o template de dados do ListBox em WPF para exibir dados de tipos complexos, com várias propriedades.

por Joel Rodrigues



Como já é de conhecimento dos desenvolvedores que utilizam XAML em suas aplicações, sabemos que esta é uma linguagem de estruturação de conteúdo muito flexível. Em aplicações WPF e Silverlight, podemos utilizar toda essa flexibilidade para manipular os componentes existentes, dando-lhes formas e configurações que atendam às nossas necessidades, sem que seja preciso criar controles customizados (User Controls ou Custom Controls). Basta que trabalhemos sobre os estilos e templates dos componentes existentes, modificando sua forma e comportamento originais.

Neste artigo veremos como customizar o formato de exibição de dados em um componente ListBox, que é sem dúvida um dos mais utilizados para a apresentação de listagens para o usuário.

Em geral se utiliza o ListBox para exibir apenas tipos simples, como strings ou numéricos, pois esse é uma limitação de funcionamento do controle equivalente em outras plataformas e frameworks, incluindo Windows Forms. Porém, em WPF (bem como no Silverlight) é possível utilizar este controle para listar tipos complexos, exibindo várias propriedades em uma mesma linha.

Criaremos aqui um exemplo prático, onde simularemos uma tela em que se lista os clientes cadastrados em uma aplicação, de forma que o usuário possa visualizar alguns dados de cada cliente para poder selecionar um.

O primeiro passo é criar um novo projeto do tipo WPF Application e adicionar uma classe Cliente, que irá representar o nosso objeto modelo dessa situação (provavelmente integrante da camada Model, em uma aplicação que utilize padrões mais comuns de divisão em camadas). Está classe irá conter apenas três propriedades, de forma a simplificar o exemplo, e seu código é apresentado na Listagem 1.

Listagem 1: Classe modelo Cliente

public class Cliente
{
    private string _nome;

    public string Nome
    {
        get { return _nome; }
        set { _nome = value; }
    }

    private string _telefone;

    public string Telefone
    {
        get { return _telefone; }
        set { _telefone = value; }
    }

    private string _email;

    public string Email
    {
        get { return _email; }
        set { _email = value; }
    }        
}

Em seguida já podemos criar um ListBox na janela principal da aplicação (MainWindow.xaml), dando-lhe um nome que será usado para referenciá-lo posteriormente (Listagem 2).

Listagem 2: Adicionando um ListBox simples

<ListBox Name="listBoxClientes">
</ListBox>

Formato de exibição padrão

Por padrão, este componente está preparado para exibir dados simples, compostos por um único valor, uma vez que sua interface não é dividida em colunas, como um DataGrid. Portanto, se atribuirmos a ele uma lista de strings, por exemplo, teremos uma formatação adequada, exibindo corretamente os valores, como é feito na Listagem 3 e visualizado na Figura 1.

Listagem 3: Exibindo uma lista de dados simples

List<string> clientes = new List<string>();
clientes.Add("Homer");
clientes.Add("Bruce");
clientes.Add("Tony");

listBoxClientes.ItemsSource = clientes;

O resultado é o seguinte:

Exibição de dados simples no ListBox

Figura 1: Exibição de dados simples no ListBox

Como já foi dito, os dados estão exibidos de forma adequada, uma vez que toda a informação está visível. Porém se realizarmos o mesmo procedimento, mas atribuindo ao ListBox uma lista de dados complexos, essa formatação passa a ser inadequada, exibindo apenas o nome do tipo de cada item listado. No exemplo da Listagem 4, atribuímos uma lista de Cliente e vemos que no ListBox aparece em todas as linhas o texto ListBoxWPF.Cliente, que é o nome do tipo do dado listado, precedido pelo namespace em que está contido (Figura 2).

Listagem 4: Listando dados complexos no ListBox

List<Cliente> clientes = new List<Cliente>();
clientes.Add(new Cliente()
{
    Nome = "Homer Simpson",
    Telefone = "3322-1100",
    Email = "homer@ossimpsons.com"
});

clientes.Add(new Cliente()
{
    Nome = "Bruce Waine",
    Telefone = "9988-7766",
    Email = "bruce@obatman.com"
});

clientes.Add(new Cliente()
{
    Nome = "Tony Stark",
    Telefone = "5544-3322",
    Email = "tony@ironman.com"
});

listBoxClientes.ItemsSource = clientes;

Dessa vez, o resultado já não é satisfatório, como vemos a seguir:

Exibição padrão de tipos complexo

Figura 2: Exibição padrão de tipos complexo

Customizando o template de dados

De fato o resultado visto na Figura 2 não é isso que desejamos, pois nossa classe possui várias propriedades que precisam ser visualizadas pelo usuário. Para resolver esse problema, recorremos à já citada flexibilidade da XAML, que nos permite customizar o chamado template de dados do ListBox.

Para fazer isso, devemos inserir entre as tags de abertura e fechamento do ListBox a tag e dentro dela a , como veremos na Listagem 5. Dentro da tag DataTemplate, podemos inserir componentes comuns de layout do WPF, como Grids, StackPanels e TextBlocks, de forma a obter a formatação desejada.

No caso do nosso exemplo, formataremos o ListBox para exibir o nome do cliente na parte superior da linha, e as informações de telefone e email logo abaixo, com fonte menor. Para isso, utilizaremos um Grid, definindo algumas linhas e colunas (Listagem 5).

Listagem 5: Customizando o template de dados do ListBox

<ListBox Name="listBoxClientes">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="300"/>
                    <ColumnDefinition Width="300"/>
                </Grid.ColumnDefinitions>
                <TextBlock Text="{Binding Path=Nome}" FontSize="30" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"/>
                <TextBlock Text="{Binding Path=Telefone}" FontSize="20" Grid.Row="1" Grid.Column="0"/>
                <TextBlock Text="{Binding Path=Email}" FontSize="20" Grid.Row="1" Grid.Column="1"/>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

No código acima, além do que já foi comentado, é necessário destacar a forma como foi atribuído valor à propriedade Text dos TextBlocks. Através do objeto Binding podemos ligar as propriedades de um componente visual às de um objeto que é fonte de dados. No exemplo, o texto dos TextBlocks foi ligado às propriedades Nome, Telefone e Email da classe cliente. Quando a aplicação é executada, à cada linha do ListBox é atribuído um Cliente da lista. Assim, a propriedade indicada no Binding é buscada neste objeto e seu valor é exibido ali.

O resultado agora é exibido na Figura 3, onde vemos que todas as propriedades estão visíveis e com a formatação desejada.

Exibição formatada de tipos complexos

Figura 3: Exibição formatada de tipos complexos

Seguindo o molde do exemplo demonstrado neste artigo o leitor poderá realizar mais customizações, adicionando mais componentes visuais e dando forma às linhas do ListBox.

Obrigado pela leitura e até o próximo artigo.

Joel Rodrigues

Joel Rodrigues - Técnico em Informática - IFRN Cursando Bacharelado em Ciências e Tecnologia - UFRN Programador .NET/C# e Delphi há quase 3 anos, já tendo trabalhado com Webservices, WPF, Windows Phone 7 e ASP.NET, possui ainda conhecimentos em HTML, CSS e Javascript (JQuery).