SilverLight 4 - Usando o controle DataGrid


Se você precisa criar aplicações que tratam com uma grande quantidade de dados, então um controle como o DataGrid do SIlverLight 4 é vital. Este controle exibe os dados em um formato tabular e permite a atualização, inclusão e exclusão de dados inline, bem como a ordenação dos dados em colunas através de um clique no cabeçalho e o agrupamento de forma que você pode criar níveis nos dados.

Desde a versão 2 o SilverLight possui um poderoso controle DataGrid que se apresenta como um boa solução para o tratamento de grande quantidade de informação em um navegador. Ele reside no namespace System.Windows.Controls mas não esta incluído por padrão nos assemblies que são instalados com o SilverLight. Ao utilizá-lo em sua aplicação o SilverLight irá embutir diversos assemblies em um arquivo XAP.

Com o objetivo de manter um bom desempenho o controle DataGrid do SilverLight possui uma recurso conhecido como UI virtualization que faz com que o SilverLight somente crie itens que estão atualmente visíveis. Dessa forma mesmo que você esteja tratando com milhões de linhas, o DataGrid irá ter um desempenho muito bom.

Neste artigo vamos criar uma aplicação SilverLight onde iremos ter o seguinte cenário:

Objetivo : Criar uma coleção de objetos Livros e exibir esta coleção e um controle DataGrid customizado;

premissas:

- Os usuários não poderão alterar os dados nem mover as colunas do DataGrid;
- A apresentação visual do DataGrid deve ser customizada;
- Os separadores verticais das colunas deverão ser ocultos e os horizontais deve ter uma cor diferente;
- Devemos tratar o evento LoadingRow que nos dá acesso aos valores que estão vinculados e baseados neste valor vamos realizar alterações a aparência visual das linhas;

Abra o Visual Web Developer 2010 Express Edition e crie um novo projeto com o nome SilverLight_DataGrid usando a linguagem Visual Basic;

No menu File-> New Project selecione Visual Basic -> SilverLight e a seguir o template SilverLight Application informando o nome SilverLight_DataGrid;

Clique em OK;

Na seguinte janela de diálogo apenas confirme as opções e clique em OK;

Será criado uma solução com dois projetos: O projeto SilverLight e o Projeto Web;

O controle DataGrid é definido no namespace System.Windows.Controls mas por padrão este namespace não esta relacionado quando criamos o aplicativo SilverLight.

Por isso no menu Project selecione Add Reference e na guia .NET selecione os componentes: System.Windows.Controls.Data e System.Windows.Controls.DataInput conforme a figura abaixo:

Agora devemos incluir as seguintes declarações no projeto:

System.ComponentModel.DataAnnotations
System.Windows.Controls.Data
System.Windows.Controls.Data.Input
System.Windows.Data

Vamos agora criar no projeto SilverLight as classes Livro, Categoria e Idiomas que irão servir como fonte de dados para a nossa aplicação e serão o domínio de nossa aplicação;

Clique com o botão direito sobre o projeto SilverLight (SilverLight_DataGrid) e selecione Add Class informando a seguir o nome da classe;

1- Classe Livro.vb

Public Class Livro

    Public Property Titulo() As String
        Get
            Return m_Titulo
        End Get
        Set(ByVal value As String)
            m_Titulo = value
        End Set
    End Property
    Private m_Titulo As String
    Public Property Autor() As String
        Get
            Return m_Autor
        End Get
        Set(ByVal value As String)
            m_Autor = value
        End Set
    End Property
    Private m_Autor As String
    Public Property Paginas() As Integer
        Get
            Return m_Paginas
        End Get
        Set(ByVal value As Integer)
            m_Paginas = value
        End Set
    End Property
    Private m_Paginas As Integer
    Public Property Categoria() As Categoria
        Get
            Return m_Categoria
        End Get
        Set(ByVal value As Categoria)
            m_Categoria = value
        End Set
    End Property
    Private m_Categoria As Categoria
    Public Property Editor() As String
        Get
            Return m_Editor
        End Get
        Set(ByVal value As String)
            m_Editor = value
        End Set
    End Property
    Private m_Editor As String
    Public Property Idioma() As Idiomas
        Get
            Return m_Idioma
        End Get
        Set(ByVal value As Idiomas)
            m_Idioma = value
        End Set
    End Property
    Private m_Idioma As Idiomas
End Class

Repita o procedimento para classe Categoria.vb e inclua o seguinte código :

Public Enum Categoria
   Aventura
   Ficção
   Computação
   Biografia
   Poesias
End Enum

Faça o mesmo para a classe Idiomas.vb :

Public Enum Idiomas
    Inglês
    Italiano
    Espanhol
    Português
End Enum

Agora no arquivo code-behind de MainPage.xaml.vb vamos incluir o código no construtor conforme abaixo:


    Private livroColecao As List(Of Livro)

    Public Sub New()
        InitializeComponent()
        carregaLivros()
    End Sub

A rotina carregaLivros() é que irá preencher em memória a nossa coleção de objetos livros. Para isso vamos definir esta rotina com o seguinte código:

Private Sub carregaLivros()
        livroColecao = New List(Of Livro)()

        Dim livro1 As New Livro()
        livro1.Titulo = "ASP, ADO e banco de dados na web "
        livro1.Autor = "José Carlos Macoratti"
        livro1.Idioma = Idiomas.Português
        livro1.Paginas = 250
        livro1.Editor = "Editora Visual Books"
        livro1.Categoria = Categoria.Computação
        livroColecao.Add(livro1)

        livro1 = New Livro()
        livro1.Titulo = "2001 Uma Odisséia no espaço"
        livro1.Autor = "Stanley Kubrick"
        livro1.Idioma = Idiomas.Português
        livro1.Paginas = 300
        livro1.Editor = "Editora B"
        livro1.Categoria = Categoria.Ficção
        livroColecao.Add(livro1)

        livro1 = New Livro()
        livro1.Titulo = "A moreninha "
        livro1.Autor = "Jose de Alencar"
        livro1.Idioma = Idiomas.Português
        livro1.Paginas = 200
        livro1.Editor = "Editora Cs"
        livro1.Categoria = Categoria.Aventura
        livroColecao.Add(livro1)

        livro1 = New Livro()
        livro1.Titulo = "Fernando Pessoa - O Cancioneiro "
        livro1.Autor = "Fernando Pessoa"
        livro1.Idioma = Idiomas.Português
        livro1.Paginas = 150
        livro1.Editor = "Editora D"
        livro1.Categoria = Categoria.Poesias
        livroColecao.Add(livro1)

        livro1 = New Livro()
        livro1.Titulo = "ASP, ADO e banco de dados na web "
        livro1.Autor = "José Carlos Macoratti"
        livro1.Idioma = Idiomas.Português
        livro1.Paginas = 250
        livro1.Editor = "Editora Visual Books"
        livro1.Categoria = Categoria.Computação
        livroColecao.Add(livro1)

        livro1 = New Livro()
        livro1.Titulo = "Poesias de Jorge Amado "
        livro1.Autor = "Jorge Amado"
        livro1.Idioma = Idiomas.Português
        livro1.Paginas = 250
        livro1.Editor = "Editora E"
        livro1.Categoria = Categoria.Poesias
        livroColecao.Add(livro1)

        livro1 = New Livro()
        livro1.Titulo = "ASP, ADO e banco de dados na web "
        livro1.Autor = "José Carlos Macoratti"
        livro1.Idioma = Idiomas.Português
        livro1.Paginas = 250
        livro1.Editor = "Editora Visual Books"
        livro1.Categoria = Categoria.Computação
        livroColecao.Add(livro1)

        livro1 = New Livro()
        livro1.Titulo = "Biografia de Roberto Carlos "
        livro1.Autor = "Jose Lima"
        livro1.Idioma = Idiomas.Português
        livro1.Paginas = 280
        livro1.Editor = "Editora F"
        livro1.Categoria = Categoria.Biografia
        livroColecao.Add(livro1)

        livro1 = New Livro()
        livro1.Titulo = "Poeias de Carlos Drummond de Andrade "
        livro1.Autor = "Carlos Durmmond de Andrade"
        livro1.Idioma = Idiomas.Português
        livro1.Paginas = 250
        livro1.Editor = "Editora VB"
        livro1.Categoria = Categoria.Poesias
        livroColecao.Add(livro1)

        livro1 = New Livro()
        livro1.Titulo = "ASP, ADO e banco de dados na web "
        livro1.Autor = "José Carlos Macoratti"
        livro1.Idioma = Idiomas.Português
        livro1.Paginas = 250
        livro1.Editor = "Editora Visual Books"
        livro1.Categoria = Categoria.Computação
        livroColecao.Add(livro1)

    End Sub

Dessa forma quando a aplicação for executada serão criados os objetos Livros , Categoria e Idiomas e a uma coleção de objetos Livros será populada com os dados para que possamos exibi-los no controle DataGrid.

A seguir, vamos adicionar um controle DataGrid para o arquivo MainPage.xaml. Por enquanto, não vamos adicionar as nenhuma propriedade no DataGrid. É aconselhável adicioná-lo para a página arrastando-o na caixa de ferramentas, para que o Visual Studio adiciona as referências corretas para os assemblies necessários no projeto, bem como acrescentar o mapeamento de espaço no código XAML.

Remova a declaração AutoGenerateColumns = "False" para que vamos ver todas as propriedades da classe Livro aparecer no DataGrid. A seguinte linha de código mostra um exemplo de DataGrid com o nome definido para DataGrid1 que o valor padrão.

Neste momento o projeto deverá apresenta a seguinte estrutura:

Pois bem e como fazemos para exibir as informações no DataGrid ???

Ora, já temos as classes definidas , já temos a coleção de livros pronta para ser preenchida com os dados e já temos o DataGrid na página principal, o que falta ???

Faltam apenas um detalhe...

No arquivo MainPage.xaml.vb volte ao construtor e inclua a seguinte linha de código: DataGrid1.ItemsSource = livroColecao conforme abaixo


    Private livroColecao As List(Of Livro)

    Public Sub New()
        InitializeComponent()
        carregaLivros()
        DataGrid1.ItemsSource = livroColecao
    End Sub

Dessa forma , usando os recurso do DataBinding do SilverLight, a propriedade ItemsSource obtém uma coleção que é usada para gerar o conteúdo do controle DataGrid.

Se executarmos o projeto agora iremos obter:

Por padrão, o DataGrid é editável pelo usuário, e para alterar este comportamento basta definir a propriedade IsReadOnly como True para não permitir que o usuário possa editar os dados no controle.

Podemos ainda bloquear a exibição definindo as propriedades CanUserResizeColumns e CanUserReorderColumns para False, e assim não permitimos aos usuários redimensionar nem reordenar as colunas do DataGrid.

Então devemos incluir as seguintes linhas de código no arquivo MainPage.XAML:

<sdk: DataGrid x: Name = "BookDataGrid"
          AutoGenerateColumns = "True "
          CanUserReorderColumns = "False"
          CanUserResizeColumns = "False"
         IsReadOnly = "True ">
</ SDK: DataGrid>


O DataGrid possui muitos mais recursos que podemos usar para ajustar a sua aparência vamos então definir as seguinte propriedades no controle:

RowBackground="#999999"
AlternatingRowBackground="#CCCCCC"
ColumnWidth="150"
RowHeight="30"
GridLinesVisibility="Horizontal"
HeadersVisibility="All"
HorizontalGridLinesBrush="Blue"

Vejamos o significado de cada uma delas:

- Nas propriedades RowBackground e AlternatingRowBackground estamos alterando a cor de fundo
- A propriedade ColumnWidth define a largura das colunas;
- A propriedade RowHeight define a altura das linhas;
- As propriedades GridLinesVisibility e HorizontalGridLinesBrush definem se as linhas de grade serão exibidas;
- A propriedade HeadersVisibility especifica que queremos um cabeçalho de linha no controle;

Executando o projeto depois destas alterações teremos:

Podemos incrementar ainda mais o nosso DataGrid e vamos fazer isso.

Vamos usar o evento LoadingRow que é acionado quando cada linha é carregada.

Vamos usar esse evento para ter acesso a cada linha e vamos alterar as suas propriedades com base em uma condição.

Vamos definir que se a categoria de um livro for Poesias a cor da linha deverá ficar com fundo amarelo.

Fazemos isso incluindo o código a seguir no evento LoadingRow:

Private Sub DataGrid1_LoadingRow(ByVal sender As System.Object, ByVal e As System.Windows.Controls.DataGridRowEventArgs) Handles DataGrid1.LoadingRow

        Dim livroExibido As Livro = TryCast(e.Row.DataContext, Livro)
        'verifica se a categoria do livro é Poesias e destaca a linha em amarelo
        If livroExibido.Categoria = Categoria.Poesias Then
            e.Row.Background = New SolidColorBrush(Colors.Yellow)
            e.Row.Height = 40
        Else
            e.Row.Background = Nothing
        End If

    End Sub

Agora é só alegria, vamos ver como ficou o nosso DataGrid ?

Do jeitinho que queríamos...

Para encerrar fica alguns lembretes:

- Ao compilar a aplicação, os assemblies correspondentes são adicionados ao arquivo XAP e isto ocorre pois ao instalar o plugin do Silverlight, os arquivos não são instalados como parte do CLR. O objetivo é manter o plugin com um tamanho o menor possível;
- No entanto quando usamos os arquivos em nossa aplicação eles são embutidos na aplicação e isso resulta em um aumento no tamanho do download do arquivo XAP;
- Na maioria das vezes, esse não é um problema. No entanto, se o tamanho do arquivo é um item importante, então é essencial ficar atento para este detalhe.
- Quando a propriedade AutoGenerateColumns é definida como True (o padrão), o DataGrid usa reflection sobre o tipo de objetos vinculados a ele. Para cada propriedade pública que ele encontra, ele gera uma coluna correspondente. Fora da caixa, o DataGrid inclui uma coluna de texto, uma coluna checkbox, e uma coluna de modelo. Para todos os tipos que não pode ser exibidos ,usa o método ToString e uma coluna de texto.
- Se quisermos que o DataGrid use o recurso de sincronização automática, a coleção deve implementar a interface INotifyCollectionChanged. Se as alterações para os objetos devem ser refletidas no DataGrid, em seguida, os objetos da coleção deve-se implementar a interface INotifyPropertyChanged

Simples , simples assim...

Pegue o projeto completo aqui: SilverLight_DataGrid.zip

Eu sei é apenas SilverLight 4 , mas eu gosto...

Referências:

José Carlos Macoratti