Um problema que muitas vezes enfrentamos quando estamos trabalhando com Grid e Listview é a classificação, pois a mesma nunca se comporta da forma esperada quando trabalhamos com datas ou números. A minha idéia neste artigo é mostrar como fazer isso utilizando uma classe personalizada. Pois bem, o primeiro passo a ser seguido é abrir o Visual Studio - no meu caso estou utilizando o VB 2008 Express - e criar um novo projeto. Vamos nomear este projeto como OrdenarListview.vb.
Feito isso clique em Project Add Class... Iremos renomear esta classe para CompararItensListview.vb.
Vamos ao código.
A primeira coisa a ser feita é definir o que você vai precisar ordenar. Neste exemplo irei demonstrar como ordenar Data, números e Texto. Iremos agora declarar nossas variáveis e criar o codigo para receber as mesmas sempre que a nossa classe for chamada. Usaremos a palavra Implements para implementar a Interface IComparer. Interfaces são classes que possuem apenas metodos e não possuem implementação, ou seja, a mesma não possui código apenas chamadas de metodos. A classe que herdar a Inteface terá que implementar o seu método e seguir o modelo de sua chamada.
'IMPLEMENTA A Interface IComparer
Implements IComparer
VERIFICAR ORDEM
Private Coluna As Integer
'VARIAVEL QUE VAI RECEBER O TIPO DE ORDEM
'QUE NOSSO LISTVIEW VAI SEGUIR
“Descending ou Ascending”
Private OrdemSort As SortOrder
Agora definiremos como iremos receber os valores Coluna e OrdemSort. Neste exemplo, os mesmos serão recebidos junto à chamada da Classe, ou seja, no procedimento Public Sub New.
Public Sub New(ByVal ColunaClique As Integer,ByVal OrdemSort As SortOrder)
Coluna = ColunaClique
Me.OrdemSort = OrdemSort
End Sub
Nosso código deve ficar assim:
Class CompararItensListview
Implements IComparer
Private Coluna As Integer
Private OrdemSort As SortOrder
Public Sub New(ByVal ColunaClique As _
Integer, ByVal OrdemSort As SortOrder)
Coluna = ColunaClique
Me.OrdemSort = OrdemSort
End Sub
End Class
O que temos que fazer agora é a função que vai organizar o Listview. O método que iremos implementar da Classe IComparer é a função compare que possui dois parâmetros: o X que representa o item que vai ser comparado; e o Y, o item anterior a este na ordem conforme exemplo abaixo:
Public Function Compare(ByVal x As Object,ByVal y As Object) As Integer _
Implements System.Collections.IComparer.Compare
End Function
Veremos agora como fazer a comparação entre os valores do Listview para estabelecer a ordem dos mesmos. O que faremos agora é uma verificação do tipo de dados da coluna selecionada e sua validação conforme este. Por exemplo, suponhamos que na sua coluna você possui datas. Para fazer esta verificação usaremos a função DateTime.TryParse que é semelhante ao IsDate do antigo VB6.
'PARA UTILIZAR A FUNÇÃO DateTime.TryParse TEMOS QUE DEFINIR UMA DATA VÁLIDA CONFORME EXEMPLO ABAIXO
Dim DataValida As DateTime
If DateTime.TryParse(CType(x, _
ListViewItem).SubItems(Coluna).Text, DataValida) Then
Perceba que na função acima utilizamos a função CType, função esta que serve para converter uma variável de um tipo para outro CType(x, ListViewItem).SubItems(Coluna).Text. Neste caso, estamos convertendo um tipo Objeto para um tipo ListViewItem e capturando assim o seu valor. Utilizaremos também a função Double.TryParse para verificar se o valor é numérico. Bem, a partir daqui não vou me ater muito, pois é apenas uma lógica de comparação para verificar a ordem que cada um vai se posicionar em relação ao item superior, conforme tabela abaixo.
0 – Igual ao item anterior fica onde esta
-1 – É menor sobe para a posição do item anterior
1 – Vai uma posição para frente
Para fazer a comparação entre os valores usaremos as funções.
DateTime.Compare – Comparar duas dadas
Convert.ToDouble – transforma em valor para comparação
String.Compare - compara duas strings
O código da nossa Classe deve ficar semelhante a este:
Class CompararItensListview
Implements IComparer
Private Coluna As Integer
Private OrdemSort As SortOrder
Public Sub New(ByVal ColunaClique As Integer, ByVal _
OrdemSort As SortOrder)
Coluna = ColunaClique
Me.OrdemSort = OrdemSort
End Sub
Public Function Compare(ByVal x As Object, ByVal y As Object) _
As Integer Implements System.Collections.IComparer.Compare
Dim OrdemItem As Integer
Dim DataValida As DateTime
Dim NumeroValido As Double
If DateTime.TryParse(CType(x, ListViewItem).SubItems(Coluna).Text, _
DataValida) Then
If DateTime.TryParse(CType(y, ListViewItem).SubItems(Coluna).Text, _
DataValida) Then
OrdemItem = DateTime.Compare(CType(x, ListViewItem).SubItems _
(Coluna).Text, CType(y, ListViewItem).SubItems(Coluna).Text)
MsgBox(CType(x, ListViewItem).SubItems(Coluna).Text)
MsgBox(CType(y, ListViewItem).SubItems(Coluna).Text)
Else
OrdemItem = -1
End If
ElseIf Double.TryParse(CType(x, ListViewItem).SubItems(Coluna) _
.Text, NumeroValido) Then
If Double.TryParse(CType(y, ListViewItem).SubItems(Coluna).Text _
, NumeroValido) Then
If Convert.ToDouble(CType(x, ListViewItem).SubItems(Coluna).Text) _
= Convert.ToDouble(CType(y, ListViewItem).SubItems(Coluna).Text) Then
OrdemItem = 0
ElseIf Convert.ToDouble(CType(x, ListViewItem).SubItems _
(Coluna).Text) > Convert.ToDouble(CType(y, ListViewItem). _
SubItems(Coluna).Text) Then
OrdemItem = 1
Else
OrdemItem = -1
End If
Else
OrdemItem = -1
End If
Else
If CType(x, ListViewItem).SubItems(Coluna).Text.Trim = "" Then
OrdemItem = 1
Else
OrdemItem = String.Compare(CType(x, ListViewItem). _
SubItems(Coluna).Text, CType(y, ListViewItem).SubItems _
(Coluna).Text)
End If
End If
'INVERTE O RETORNO EM CASO DE ORDEM DECRESCENTE
If OrdemSort = SortOrder.Descending Then
OrdemItem *= -1
End If
Return OrdemItem
End Function
End Class
Vamos ao codigo do formulário insira um Listview no Form criado e coloque o código abaixo:
Dim ColunaSelecionada As Integer = -1
Private Sub ListView1_ColumnClick(ByVal sender As Object, _
ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles ListView1.ColumnClick
'VERIFICA SE CLIQUE É NA MESMA COLUNA
'SE FOR ORDENA DECRESCENTE
If e.Column <> ColunaSelecionada Then
ColunaSelecionada = e.Column
ListView1.Sorting = SortOrder.Ascending
Else
If ListView1.Sorting = SortOrder.Ascending Then
ListView1.Sorting = SortOrder.Descending
Else
ListView1.Sorting = SortOrder.Ascending
End If
End If
'CHAMA METODO QUE IRA ORDENAR O LISTIVEW
ListView1.ListViewItemSorter = New _
CompararItensListview(e.Column, ListView1.Sorting)
End Sub
Para testar insira alguns dados no seu Listview varie as colunas com datas, numeros e texto para ver se funciona abraços e até o proximo.
Baixe o projeto completo escrito no Visual Studio 2008 no link abaixo:
Ordenar Listview