VB .NET - O Controle Listview revisitado


Eu já escrevi muitos artigos sobre o controle ListView, desde os tempos do VB6. Ele é um dos meus controles favoritos por isso resolvi voltar ao tema para recordar e mostrar como fazer a manutenção de dados XML usando o ListView.

O controle ListView é uma janela que exibe uma coleção de itens de 4 maneiras possíveis e permite muitas formas de arranjar e exibir os itens sendo muito maleável e flexível. Neste artigo eu vou mostrar o básico sobre o ListView realizando operações como incluir, editar e deletar itens.

Para recordar o básico sobre as propriedades e métodos do ListView segue abaixo um resumo dos mesmos:

O controle ListView fornece um grande número de propriedades que permite configurar sua aparência e comportamento de uma forma muito flexível. Dentre as principais propriedades citamos :
  1. View - permite alterar a forma nas quais os itens são exibidos
  2. LargeImageList , SmallImageList e StateImageList - permite especificar o objeto ImageList que contém as imagens exibidas para os itens
  3. Columns - permite o acesso a coleção que armazena os cabeçalhos das colunas
  4. Items - premite acessar os métodos para manipular os itens no controle
  5. Sorting - permite ordenar os itens alfabeticamente
  6. LabelEdit - permite ao usuário editar o texto de um item
  7. CheckedItems - permite saber quais itens estão marcados
  8. AllowColumnReorder - permite re-configurar a ordem das colunas em tempo de execução
  9. FullRowSelect - permite a seleção de um item e subitem

Além desta propriedades o controle ListView também possui métodos e eventos que podemos usar em nossas aplicações aumentando assim as capacidades do controle ListView.  Vejamos alguns deles :

  1. BeginUpdate e EndUpdate : permite incluir itens em um ListView sem redesenhar o controle a cada item que é adicionado
  2. GetItemAt - permite determinar o item cujos subitens esta sendo clicado
  3. EnsureVisible - pode ser chamado para assegurar que o item especifico esta na área visível do controle.
  4. BeferoLabelEdit e AfterLabelEdit - permite validar o texto que esta sendo editado antes e depois da alteração do texto
  5. ColumnClick - permite ativar uma rotina quando a coluna é clicada.
  6. ItemCheck - permite determinar quando a alteração no estado de um item ocorreu.

Da teoria a prática

Vou usar o Visual Basic 2008 Express Edition para criar o exemplo usado neste artigo onde irei mostrar como incluir, alterar e editar itens do ListView.

Nosso exemplo será uma lista de contatos contendo o nome e o telefone do contato. Os dados serão persistidos no arquivo XML chamado contatos.xml salvo na pasta c:\dados.

Abra o VB 2008 e crie um novo projeto do tipo Windows Forms Application com o nome ListViewNet;

No formulário padrão form1.vb inclua os controles : Label, Button e ListView conforme o leiaute abaixo:

Controles usados no formulário:
  • 2 Label - Nome e Telefone;
  • 2 TextBox - txtNome e txtTelefone ;
  • 1 ListView - lstvDados;
  • 5 Button : btnNovo, btnEditar, btnExcluir, Salvar dados
    e btnSair;

Definição das propriedades do controle ListView:

  • FullRowSelect = True
    GridLines = True
    HideSelection = False
    MultiSelect = False
    View = Details

Em nosso projeto vamos usar o namespace System.Xml pois pretendemos salvar e carregar os dados a partir de um arquivo XML. Faça a seguinte declaração no formulário :

imports System.Xml

A seguir no formulário vamos definir uma variável chamada blnNovo do tipo Boolean para indicar se estamos incluindo ou editando os dados:

Dim blnNovo As Boolean

Quando o formulário for carregado iremos exibir os dados que estão no arquivo XML no ListView para isso declare a chamada a rotina preencheLista() no evento Load do formulário:

 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        preencheLista()
    End Sub

A seguir defina a rotina preencheLista() abaixo:

 Private Sub preencheLista()
        '//////////////////////////////////////////
        '<?xml version="1.0" encoding="us-ascii"?>
        '<Agenda>
        ' <contato>
        '   <nome>Macoratti</nome>
        '   <telefone>123167999</telefone>
        '  </contato>
        '</Agenda>
        '/////////////////////////////////////////
        lstvDados.Columns.Add("Nome", 100, HorizontalAlignment.Left)
        lstvDados.Columns.Add("Telefone", 100, HorizontalAlignment.Left)

        Dim doc As New XmlDocument
        Try
            doc.Load("c:\dados\contatos.xml")
        Catch ex As Exception
            MsgBox("Erro ao ler arquivo XML.")
            Exit Sub
        End Try
        Dim nodes As XmlNodeList = doc.SelectNodes("Agenda/contato")

        For Each element As XmlElement In nodes
            Dim telefone As String = element.SelectSingleNode("telefone").InnerText
            Dim nome As String = element.SelectSingleNode("nome").InnerText
            lstvDados.Items.Add(New ListViewItem(New String() {nome, telefone}))
        Next
    End Sub

Neste código definimos as colunas do ListView que serão o cabeçalho exibindo o Nome e Telefone. A seguir carregamos o arquivo XML contatos.xml e exibimos o seu conteúdo no ListView.

Para incluir um novo contato incluímos o código a seguir no evento Click do botão de comando Novo:

 Private Sub btnNovo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNovo.Click
        If btnNovo.Text.ToLower() = "novo" Then
            txtNome.Enabled = True
            txtTelefone.Enabled = True
            btnNovo.Text = "Salvar"
            btnEditar.Text = "Cancelar"
            btnDeletar.Enabled = False
            txtNome.Text = ""
            txtTelefone.Text = ""
            blnNovo = True
        Else
            txtNome.Enabled = False
            txtTelefone.Enabled = False
            btnNovo.Text = "Novo"
            btnEditar.Text = "Editar"
            btnDeletar.Enabled = True
            If blnNovo Then
                If txtNome.Text = String.Empty Then
                    MsgBox("Informe o nome.")
                    Return
                End If
                If txtTelefone.Text = String.Empty Then
                    MsgBox("Informe o telefone.")
                    Return
                End If
                IncluirItensNoListView(lstvDados, txtNome.Text, txtTelefone.Text)
            Else
                EditarItensNoListView()
            End If
        End If
    End Sub

Este código habilta/desabilita os botões apropriados a tarefa a ser realizada e conforme a opção selecionda usa as rotinas para incluir ou editar dados:

- A rotina incluirItensNoListView() passa como parâmetro o controle ListView e os valores que vamos incluir, no caso, nome e telefone informados nas caixas de texto do formulário;

- A rotina EditarItensNoListView() apenas a chama rotina para efetuar a edição das informações;

A rotina incluirItensNoListView() é a seguinte:

   Private Sub IncluirItensNoListView(ByVal lv As ListView, ByVal item As String, ByVal ParamArray subitem As String())
        ''Geralmente a primeira coluna é o item raiz
        ''As colunas restantes são sub-itens
        ' cria o item.
        Dim novo_item As ListViewItem = lstvDados.Items.Add(txtNome.Text)
        ' cria os sub-items.
        For i As Integer = subitem.GetLowerBound(0) To subitem.GetUpperBound(0)
            novo_item.SubItems.Add(subitem(i))
        Next i
    End Sub 

nela estamos criando o item e o subitem informados para serem gravados.

A rotina EditarItensNoListView() mostrada a seguir verifica se existe um item selecionado no ListView e efetua a edição.

Private Sub EditarItensNoListView()
        'verifica se existem um item selecionado para alterar
        If lstvDados.SelectedItems.Count > 0 Then
            lstvDados.SelectedItems(0).Text = txtNome.Text
            lstvDados.SelectedItems(0).SubItems(1).Text = txtTelefone.Text
        End If
    End Sub

O código para editar dados no ListView do evento Click do botão Editar apenas verifica se

 Private Sub btnEditar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEditar.Click
        If txtNome.Text.Length > 0 Then
            If btnEditar.Text.ToLower() = "editar" Then 
                txtNome.Enabled = True
                txtTelefone.Enabled = True
                btnNovo.Text = "Salvar"
                btnEditar.Text = "Cancelar"
                btnDeletar.Enabled = False
                blnNovo = False
            Else 'cancela
                txtNome.Enabled = False
                txtTelefone.Enabled = False
                btnNovo.Text = "Novo"
                btnEditar.Text = "Editar"
                btnDeletar.Enabled = True
            End If
        Else
            MessageBox.Show("Selecone um item para editar...")
        End If

    End Sub

Para excluir um item usamos o código a seguir no evento Click do botão Excluir e usa o método Remove do controle ListView para remover o item:

Private Sub btnDeletar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDeletar.Click
        'verifica se existe um item selecionado para exclusão
        If lstvDados.SelectedItems.Count > 0 AndAlso MessageBox.Show("Deseja deletar este item ?", "Confirma", MessageBoxButtons.YesNo) = _ 
Windows.Forms.DialogResult.Yes Then
            lstvDados.SelectedItems(0).Remove()
        End If
    End Sub

Para salvar os dados do controle ListView no arquivo XML contatos.xml usamos o código abaixo:

 Private Sub btnSalvarDadosXML_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvarDadosXML.Click

        Dim x As New Xml.XmlTextWriter("C:\dados\contatos.xml", System.Text.Encoding.ASCII)

        Dim i As Integer
        x.WriteStartDocument()
        x.WriteStartElement("Agenda")
        i = lstvDados.Items.Count
        For Each lvi As ListViewItem In lstvDados.Items
            x.WriteStartElement("contato")
            x.WriteElementString("nome", lvi.Text)
            x.WriteElementString("telefone", lvi.SubItems(1).Text)
            x.WriteEndElement()
        Next
        x.WriteEndDocument()
        x.Close()

    End Sub

No botão Buscar temos o código abaixo onde chamamos a rotina procuraritem():

Private Sub btnProcurar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnProcurar.Click
        If Not txtNome.Text = String.Empty Then
            procurarItem()
        End If
    End Sub

A rotina procurarItem() usa o método FindItemWithText para localizar um item no controle e em caso positivo marca o item e o seleciona destacando dos demais:

O método FindItemWithText(String) Localiza o primeiro ListViewItem que começa com o valor de texto especificado.

O parâmetro String  pode especificar uma Sub-cadeia do texto correspondente desejado. Além disso, esse método retornará o primeiro item que começa com o texto especificado.

O método de FindItemWithText retorna uma referência nula (Nothing no Visual Basic) se a lista estiver Vazio ou não há nenhum item correspondente.

Private Sub procurarItem()
        Dim lvItem As ListViewItem = lstvDados.FindItemWithText(txtNome.Text, False, 0, True)
        If (lvItem IsNot Nothing) Then
            lvItem.Checked = True
            lvItem.Selected = True
            lvItem.ForeColor = Color.Blue
        End If
    End Sub

Obs: A rotina para procurar um item precisa ser melhor ajustada no projeto. Deixo isso como um exercício.

A seguir temos a figura do resultado da execução do projeto onde incluímos e editamos alguns itens. Ao lado temos o respectivo XML gerado:

<?xml version="1.0" encoding="us-ascii"?>
<Agenda>
  <contato>
    <nome>Macoratti</nome>
    <telefone>111111</telefone>
  </contato>
  <contato>
    <nome>teste</nome>
    <telefone>1111</telefone>
  </contato>
  <contato>
    <nome>maria</nome>
    <telefone>888877777</telefone>
  </contato>
  <contato>
    <nome>Janeiro</nome>
    <telefone>999999988888888</telefone>
  </contato>
  <contato>
    <nome>paulo</nome>
    <telefone>098098</telefone>
  </contato>
  <contato>
    <nome>carlos</nome>
    <telefone>4444444</telefone>
  </contato>
</Agenda>

Dessa forma criamos um pequeno projeto capaz de efetuar as informações em um controle ListView persistindo os dados em um arquivo XML.

Aguarde mais artigos sobre VB .NET.

Pegue o projeto completo aqui:  ListViewNet.zip

Eu sei é apenas VB .NET mas eu gosto...

Referências:


José Carlos Macoratti