Search code examples
vb.netsortinglistview

VB How to sort ListView in ascending and descending order


I cannot figure out why this is not working. I have a ListView that I would like to be able to sort in both ascending and descending order. It appears when stepping through the code line by line that all goes well except lvItems.Sorting will not equal Descending. It is in a constant loop between None{0} and Ascending{1}.

Here is the Form class:

Private Sub lvItems_ColumnClick(sender As Object, e As System.Windows.Forms.ColumnClickEventArgs) Handles lvItems.ColumnClick

    ' If current column is not the previously clicked column
    ' Add
    If e.Column <> sortColumn Then

        ' Set the sort column to the new column
        sortColumn = e.Column

        'Default to ascending sort order
        lvItems.Sorting = SortOrder.Ascending

    Else

        'Flip the sort order
        If lvItems.Sorting = SortOrder.Ascending Then
            lvItems.Sorting = SortOrder.Descending
        Else
            lvItems.Sorting = SortOrder.Ascending
        End If
    End If

    'Set the ListviewItemSorter property to a new ListviewItemComparer object
    Me.lvItems.ListViewItemSorter = New ListViewItemComparer(e.Column, lvItems.Sorting)

    ' Call the sort method to manually sort
    lvItems.Sort()

End Sub

And here is the ListViewItemComparer Class:

Public Class ListViewItemComparer

    Implements IComparer

    Private col As Integer
    Private order As SortOrder

    Public Sub New()
        col = 0
        order = SortOrder.Ascending
    End Sub

    Public Sub New(column As Integer, order As SortOrder)
        col = column
        Me.order = order
    End Sub

    Public Function Compare(x As Object, y As Object) As Integer Implements System.Collections.IComparer.Compare

        Dim returnVal As Integer = -1

        Try

            ' Attempt to parse the two objects as DateTime
            Dim firstDate As System.DateTime = DateTime.Parse(CType(x, ListViewItem).SubItems(col).Text)
            Dim secondDate As System.DateTime = DateTime.Parse(CType(y, ListViewItem).SubItems(col).Text)

            ' Compare as date
            returnVal = DateTime.Compare(firstDate, secondDate)

        Catch ex As Exception

            ' If date parse failed then fall here to determine if objects are numeric
            If IsNumeric(CType(x, ListViewItem).SubItems(col).Text) And
                IsNumeric(CType(y, ListViewItem).SubItems(col).Text) Then

                ' Compare as numeric
                returnVal = Val(CType(x, ListViewItem).SubItems(col).Text).CompareTo(Val(CType(y, ListViewItem).SubItems(col).Text))

            Else
                ' If not numeric then compare as string
                returnVal = [String].Compare(CType(x, ListViewItem).SubItems(col).Text, CType(y, ListViewItem).SubItems(col).Text)
            End If

        End Try

        ' If order is descending then invert value
        If order = SortOrder.Descending Then
            returnVal *= -1
        End If

        Return returnVal

    End Function

End Class

No matter what data I put in I only seem to get ascending order. Let me know if more information is necessary.


Solution

  • I was able to resolve issue thanks to @jmcilhinney's comment. Instead of using both Sorting and ListViewItemSorter, I created a string variable ordering and assigned it the appropriate sort order (see below for final solution).

            'If current column is not the previously clicked column
            'Add
            If e.Column <> sortColumn Then
    
                ' Set the sort column to the new column
                sortColumn = e.Column
    
                'Default to ascending sort order
                ordering = "Ascending"
    
            Else
    
                'Flip the sort order
                If ordering = "Ascending" Then
                    ordering = "Descending"
                Else
                    ordering = "Ascending"
                End If
            End If
    
            'Set the ListviewItemSorter property to a new ListviewItemComparer object
            lvItems.ListViewItemSorter = New ListViewItemComparer(e.Column, ordering)
    
            'Call the sort method to manually sort
            lvItems.Sort()