 VB.NET
- Uma introdução básica as controles de lista
VB.NET
- Uma introdução básica as controles de lista
Neste artigo vou falar um pouco sobre os controles de lista : ListBox , CheckedListBox e Combobox. Todos estes controles derivam da classe base ListControl . Esta classe é uma classe abstrata (MustInherit no VB.NET) e não pode ser instanciada , mas as classes concretas citadas e delas derivadas podem ser instanciadas e usadas normalmente conforme veremos a seguir.
A classe ListControl fornece muito das funcionalidades comuns entre estes três controles. A tabela abaixo lista as cinco propriedades nativas da classe ListControl que são herdadas pelas classes derivadas.
Propriedades da classe ListControl
| Propriedade | Tipo | Descrição | 
|---|---|---|
| DataSource | Object | Read/write. Define a fonte de dados para o controle de lista | 
| DisplayMember | String | Read/write. Define a propriedade da fonte de dados a ser exibida no controle. | 
| SelectedValue | Object | Read/write. Contém o valor do item selecionado atual definido pela propriedade ValueMember. Se ValueMember nao estiver definido retorna : object.ToString( ). | 
| ValueMember | String | Read/write. Define a propriedade da fonte de dados retornada pela propriedade SelectedValue. Pode ser anulada atribuindo uma string vazia ou uma referencia Null. | 
| SelectedIndex | Integer | Read/write. O indice baseado no valor inicial zero do item atualmente selecionado. O valor -1 indica que nenhum item esta selecionado. | 
Estas propriedades incluem a propriedade DataSource e muitas propriedades úteis . Nas tabelas a seguir temos as propriedades/métodos que não são membros da classe ListControl mas são membros para todos os três controles derivados desta classe. Elas incluem propriedades para definir a aparência do controle e propriedades relacionadas com a coleção de itens dos controles.
Propriedades comum a todos os controles de lista
| Propriedade | tipo | Descrição | 
|---|---|---|
| IntegralHeight | Boolean | Read/write. Se True (o padrão) o controle se redimensiona para evitar mostrar itens parciais. | 
| DrawMode | DrawMode | Read/write. 
		Define o modo de desenho para o controle. Os valores válidos são: - DrawMode.Normal (padrão), DrawMode.OwnerDrawFixed, and DrawMode.OwnerDrawVariable. | 
| ItemHeight | Integer | Read/write. Altura de um item no controle em pixels. | 
| Items | ObjectCollection | Read-only. Coleção de itens no controle. | 
| PreferredHeight | Integer | Read-only. A altura de todos os itens no controle em pixels. Esta é a altura que o controle precisa para exibir todos os itens se efetuar uma rolagem vertical. | 
| SelectedItem | Object | Read/write. O item atualmente selecionado no controle. | 
| Sorted | Boolean | Read/write. Se false (o padrão), os itens no controle não estão ordenados e novos itens são incluídos no final da lista. De outra forma eles são ordenados em ordem crescente , em ordem alfabética , e case-insensitive. Se True , o indice de um item especifico pode ser alterado conforme novos itens forem sendo incluídos. | 
| Text | String | Read/write. O texto associado ao item atualmente selecionado. | 
Métodos comum a todos os controles de lista
| Método | Descrição | 
|---|---|
| BeginUpdate | Evita o redesenho do controle enquanto itens são incluídos na coleção de itens. | 
| EndUpdate | Recupera o desenho do controle depois que BeginUpdate foi invocado. | 
| FindString | Overloaded. Retorna um índice baseado em zero do primeiro item na coleção de itens que inicia com uma string definida. | 
| FindStringExact | Overloaded. Retorna um índice baseado em zero do primeiro item da coleção deitens que coincide exatamente com a string definida | 
Preenchendo um Controle de Lista
Vamos então ao que interessa. 

Há duas maneiras de preencher os controles de lista:
A propriedade Items representa uma coleção de objetos contidos em uma lista ; como toda a coleção de objetos , ela implementa as interfaces IList, ICollection e IEnumerable e fornece métodos para inclui , excluir e manipular a coleção. Abaixo temos os métodos mais usados para isto:
Métodos mais comuns usados em ObjectCollection
| Método | Descrição | 
|---|---|
| Add | Inclui um novo objeto a coleção de itens atual. Retorna um índice baseado em zero de um item na coleção. | 
| AddRange | Inclui um array de objetos na coleção | 
| Clear | Remove todos os itens de uma coleção. | 
| Contains | Retorna true se o objeto especificado é encontrado na coleção. | 
| CopyTo | Copie a coleção completa para um objeto array definido iniciando no índice especificado. | 
| IndexOf | Retorna um índice baseado em zero de um objeto definido dentro da coleção. Se o objeto não for encontrado retorna -1. | 
| Insert | Insere um objeto em uma coleção de um índice definido. Se o If the Sorted property is true, the index is ignored. | 
| Remove | Remove o objeto especificado da coleção.Todos os objetos se movem uma posição. | 
| RemoveAt | Remove o objeto da coleção na posição definida pelo índice.Todos os objetos se movem uma posição. | 
Se olharmos as tabelas veremos que a coleção Items é do tipo ObjectCollection , acima temos os métodos mais usados de ObjectCollection.
Note porem que não existe uma classe ObjectCollection. Cada um dos controles derivados da classe ListControl possui a sua própria classe ObjectCollection: ObjectCollection, CheckedListBox.ObjectCollection, e ComboBox.ObjectCollection. Porém todas as 3 classes contém essencialmente os mesmos métodos com algumas exceções que veremos a seguir.
Além disto a classe ObjectCollection possui a propriedade de somente-leitura Count que retorna o número de itens na coleção e a propriedade Item de leitura/escrita que é um indexador dentro da coleção. Vamos falar delas logo , logo...
Quando você usa o IDE do VS.NET , strings podem ser incluídas em uma coleção de itens em tempo de desenho usando o Editor de Strings para Coleções. O acesso é feito quando você clica no botão com três pontos(...) perto da propriedade Items na janela Property. A seguir basta digitar a relação de strings e clicar no botão OK.
|  |  | 
O editor utiliza o método AddRange para incluir strings para a coleção items. O código que faz isto reside no método InitializeComponente gerado pelo VS.NET.
A segunda maneira de preencher um controle de lista é vincular o controle a uma fonte de dados usando a propriedade DataSource. A fonte de dados pode ser qualquer objeto que implementa a interface IList. Esta interface representa uma coleção de objetos que são individualmente acessados via index:
A propriedade DataSource vincula os dados na fonte de dados do controle. Geralmente um DataSource possui um ou mais membros , tais como DataColumns em um DataTable.
Vamos supor que você tem um banco de dados que contém todos os estados do país. Suponha que esta tabela possua duas colunas : UF e Nome do estado. Você gostaria de exibir o nome do estado no controle de lista , mas gostaria de passar a abreviação para o programa que esta acessando o controle. O código que faz este serviço é o seguinte :
| ' Cria uma conexão e um comando Dim conStr As String = "Provider=Microsoft.JET.OLEDB.4.0;data source=d:\teste\northwind.mdb" Dim sqlStr As String = "SELECT * from estados" ' Cria um objeto connection Dim conn As OleDbConnection = New OleDbConnection(conStr) ' Cria o objeto dataadapter Dim da As OleDbDataAdapter = New OleDbDataAdapter(sqlStr, conn) ' Cria o dataset e preenche com os dados do datadapter Dim ds As DataSet = New DataSet da.Fill(ds, "estados")  ' vincula o DefaultView do dataset ao controle
 Dim dv As DataView = ds.Tables("estados").DefaultView
 lb.DataSource = dv
 lb.DisplayMember = "NomeEstado"
 lb.ValueMember = "UF"
 lb.SelectedIndex = 0conn.Close() |  | 
O código acima apenas faz a conexão com a fonte de dados e exibe os dados em um controle ListBox. Para extrair o valor do membro do controle para processamento podemos usar o evento SelectedValueChanged :
|   Dim strEstado As String
  If lb.SelectedIndex <> -1 Then
     strEstado = CType(lb.SelectedItem, DataRowView)("NomeEstado").ToString()
     lblselecao.Text = " Selecionou : " & strEstado
  End If		 | 
Você dever realizar um cast (conversao forçada) a propriedade SelectedValue para um tipo correto (neste caso um string) pois a propriedade é herdada de um tipo objeto, como cada item da coleção Items.
Abaixo temos o código onde um controle ListBox é preenchido a partir de um tabela sem usar a propriedade DataSource . Ao invés disto fazemos uma iteração na tabela e o método add da classe Items é chamado para cada registro.
| Dim connectionString As String connectionString = "Provider=Microsoft.JET.OLEDB.4.0;data source=d:\teste\northwind.mdb"    Dim commandString As String
    commandString = "Select * from estados"Dim da As New OleDbDataAdapter(commandString, connectionString) Dim ds As New DataSet da.Fill(ds, "estados")     Dim dt As DataTable
    dt = ds.Tables(0)    Dim linha As DataRow
    For Each linha In dt.Rows
        lb.Items.Add(linha("UF") & ": " & linha("NomeEstado"))
    Next |  | 
Esta técnica oferece dois benefícios sobre o databinding. O Primeiro é que muito conveniente exibir a concatenação de um ou mais campos como um string texto. O segundo deriva do fato de que se a propriedade DataSource é usada, então a coleção Items da lista não pode ser modificada.
Esta técnica evita que seja possível modificar os itens da coleção. Porém você perde a habilidade de exibir um valor na lista representado pela propriedade DisplayMember e retornar um valor diferente para processamento posterior representado pela propriedade ValueMember.
Você pode usar a propriedade DataSource e a vinculação de dados e alem disto preservar o uso das propriedades DisplayMember e ValueMember enquanto ainda estiver concatenando os campos e o texto. Vejamos um exemplo onde iremos retornar o nome do Estado e a UF da tabela estados de um banco de dados northwind.mdb.(Criei esta tabela no banco de dados para o artigo)
| Dim connectionString As String
        connectionString = "Provider=Microsoft.JET.OLEDB.4.0;data source=d:\teste\northwind.mdb"        Dim commandString As String
        commandString = "Select * from estados"Dim da As New OleDbDataAdapter(commandString, connectionString) Dim ds As New DataSet da.Fill(ds, "estados")         Dim dt As DataTable
        dt = ds.Tables(0)
       ' vincula o controle a tabela
       lb.DataSource= dt;
       lb.DisplayMember = "NomeEstado";
       lb.ValueMember = "UF"; | 
A consulta SQL contida na string de comando retorna a coluna código mais a concatenação do primeiro nome com o sobrenome separados por uma virgula que formam o campo nome.
Logo depois de definir a propriedade DataSource , a propriedade DisplayMember é definida para membro NomeEstado e a propriedade ValueMember é definida para o membro UF. O resultado obtido pode ser exibido em um ListBox.
O código do evento Click do botão de comando é exibido abaixo. Se houver uma seleção no ListBox, sua propriedade SelectionMode é definida para o valor One:
|     If lb.SelectedIndex <> -1 Then
            Dim s As String = CType(lb.SelectedItem, DataRowView)("NomeEstado").ToString()
            MessageBox.Show("Valor :  " + lb.SelectedValue.ToString() + vbCrLf + "Exibir :  " + s)
        Else
            MessageBox.Show("Nada selecionado")
      End If | 
O resultado da caixa de mensagem é mostrado abaixo:

No exemplo a propriedade SelectedValue e o método ToString mostra o membro especificado pela propriedade ValueMember porém exibe o membro definido pela propriedade DisplayMember . Você poderia substituir o argumento do MessageBox com o seguinte codigo:
MessageBox.Show("Valor : " + lb.SelectedValue.ToString(  ) + vbCrLf +  "Exibir :" + lb.SelectedItem.ToString(  ))
Ao fazer isto o resultado será o exibido abaixo. Este resultado evidencia que os itens na coleção Items são objetos e neste caso objetos do tipo DataRowView.

Você poderia esperar que os itens na coleção Items deste exemplo fossem objetos DataRow , desde que a propriedade DataSource é um DataTable porém sempre que um dado é exibido em um formulário Windows Forms ele é exibido como um objeto DataRowView.
Por causa disto o código realiza um cast no SelectedItem para um objeto DataRowView e chama o método ToString para convertê-lo para uma string para exibir no MessageBox.
Isto funciona bem , exceto por dois efeitos colaterais : isto requer que você informe o nome do membro e , se o ListBox fosse definido como sendo multiselected ele irá exibir somente o primeiro elemento selecionado.
Para tratar um multi-seleção no controle devemos usar o seguinte código:
| Dim strMsg As String = ""  If lb.SelectedIndex <> -1 Then
    Dim item As Object
    For Each item In lb.SelectedItems
       Dim s1 As String = CType(item, DataRowView)(lb.ValueMember).ToString()
       Dim s2 As String = CType(item, DataRowView)(lb.DisplayMember).ToString()
       trMsg += "Valor :  " + s1 + vbCrLf + "Exibir :  " + s2 + vbCrLf + vbCrLf
   Next
       MessageBox.Show(strMsg)
Else
      MessageBox.Show("Nada selecionado")
End If |  | 
A solução do código acima realiza uma iteração através da coleção SelectedItems, construindo uma string para exibir no controle MessageBox. O nome dos membros não estão incluídos fixos no código , mas as propriedades ValueMember e DisplayMember são usadas diretamente para inspecionar o interior dos objetos DataRowVIew. O resultado será os itens selecionados exibidos.
Os exemplos acima mostram diferentes formas de retornar o texto associado com um item na coleção Items usando as propriedades SeletecdItem, SelectedItems e SelectedValue. A classe ListControl fornece também o método GetItemText que simplifica esta tarefa pois toma um item objeto como um argumento e retorna uma string.
Usando o método GetItem , você pode reescrever e consolidar os exemplos acima :
|  Dim strMsg As String = ""
        If lb.SelectedIndex <> -1 Then            '  para seleção simples no listbox
            MessageBox.Show("Item Texto :  " + lb.GetItemText(lb.SelectedItem))            '  para seleção múltiplas no listbox
            Dim item As Object
            For Each item In lb.SelectedItems
                Dim s1 As String = CType(item, DataRowView)(lb.ValueMember).ToString()
                Dim s2 As String = CType(item, DataRowView)(lb.DisplayMember).ToString()
                Dim s3 As String = lb.GetItemText(item)
                strMsg += "Valor: " + s1 + vbCrLf + "Exibe : " + s2 + vbCrLf + "Item texto : " + s3 + vbCrLf + vbCrLf
            Next
            MessageBox.Show(strMsg)
        Else
            MessageBox.Show("Nada Selecinado")
        End If
 | 
Finalmente existe um outra forma ainda simples de retornar e exibir um item. A propriedade Text da classe derivada de LisControl sobre-escreve a propriedade Text do controle Base.
A propriedade Text dos controles ListBox, CheckedListBox, and ComboBox reflete não a string associada com o próprio controle , mas o item atualmente selecionado. . No caso de controles que suportam multi selecao (ListBox and CheckedListBox) ele corresponde ao texto do primeiro item selecionado.
Para exibir o valor de um simples item selecionado usamos o seguinte código:
MessageBox.Show("Text:  " + lb.Text)
Creio que deu para você ter uma visão panorâmica dos controles de lista e obter os conceitos básicos para saber usá-los em suas aplicações .NET.
Arriverdeci !!!

| Veja os 
    Destaques e novidades do SUPER DVD Visual Basic 
(sempre atualizado) : clique e confira ! Quer migrar para o VB .NET ? 
 Quer aprender C# ?? 
 Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? | 
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a 
Objetos com VB .NET
