0

This is a short bit of code that shows how to implement sorting on columns in a details-mode ListView. Suggestions for improvement are always welcome. One possible improvement would be to modify the column headers to indicate which column is being sorted and in which direction.

Edited by Reverend Jim

'                                                                                   
'  Name:                                                                            
'                                                                                   
'    ListViewSortDemo                                                               
'                                                                                   
'  Description:                                                                     
'                                                                                   
'    Demo code to show how to sort by clicking on a ListView column.                
'                                                                                   
'  Notes:                                                                           
'                                                                                   
'    To create the form for this project you only have to add a ListView control    
'    to a blank form. Put the listview into details mode and add four columns.      
'    Set the widths of all columns to 100. Set the font to Courier New (or some     
'    other monospaced font). All listview entries for this demo are added at run    
'    time.                                                                          
'                                                                                   
'    I keep track of the current sort order by using the Tag property of each       
'    column. I use +1 and -1 because it is so easy to toggle.                       
'                                                                                   
'    In order to sort you must create a custom class that implements the IComparer  
'    interface. It will have one method named Compare which will return one of      
'    three values indicating the result of the comparison. If you are sorting from  
'    smallest to largest then the values returned are:                              
'                                                                                   
'      -1  -  item1 < item2                                                         
'       0  -  item1 = item2                                                         
'      +1  -  item1 > item2                                                         
'                                                                                   
'    If you are sorting from largest to smallest then reverse the signs.            
'                                                                                   
'    The Compare function need not be restricted to one column or be based on a     
'    strict numerical or string comparison. This demo uses three custom compare     
'    classes.                                                                       
'                                                                                   
'    NumericSorter                                                                  
'                                                                                   
'      Sorts all rows based on the integer values in column 1                       
'                                                                                   
'    SumSorter                                                                      
'                                                                                   
'      Sorts all rows based on the sums of the digits in column 2                   
'                                                                                   
'    NameSorter                                                                     
'                                                                                   
'      Does a two column sort. It sorts all rows based on the string value in       
'      column 3, then the string value in column 4.                                 
'                                                                                   
'  Audit:                                                                           
'                                                                                   
'    2012-08-12  Reverend Jim original code                                         
'                                                                                   

Public Class Form1

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

        'Keep track of the last selected sort order using the Tag property

        For Each col As Object In ListView1.Columns
            col.tag = -1
        Next

        'populate a four column listview with some data

        AddRow(ListView1, {"87013", "87013", "Fred", "Stalder"})
        AddRow(ListView1, {"90215", "90215", "Virgil", "Samms"})
        AddRow(ListView1, {"600021", "600021", "Rod", "Kinnison"})
        AddRow(ListView1, {"2457", "2457", "Fred", "Flintstone"})
        AddRow(ListView1, {"7259", "7259", "Nils", "Bergenholm"})

    End Sub

    Private Sub AddRow(lvw As ListView, data() As String)

        'add a row to the given listview

        Dim item As New ListViewItem()
        item.Text = data(0)

        For i As Integer = 1 To UBound(data)
            item.SubItems.Add(data(i))
        Next

        lvw.Items.Add(item)

    End Sub

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

        Dim lvw As ListView = sender

        'sort on the clicked column

        Select Case e.Column
            Case 0 : lvw.ListViewItemSorter = New NumericSorter
            Case 1 : lvw.ListViewItemSorter = New SumSorter
            Case 2 : lvw.ListViewItemSorter = New NameSorter(2, 3)
            Case 3 : lvw.ListViewItemSorter = New NameSorter(3, 2)
        End Select

        'Toggle sort order

        lvw.Sorting = IIf(lvw.Columns(e.Column).Tag = -1, SortOrder.Ascending, SortOrder.Descending)
        lvw.Columns(e.Column).Tag *= -1

    End Sub

    Class NumericSorter      'sorts on the first column based on the numeric value

        Implements IComparer

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

            Dim item1 As ListViewItem = x
            Dim item2 As ListViewItem = y

            If item1.ListView.Sorting = SortOrder.Ascending Then
                Return Math.Sign(CInt(item1.SubItems(0).Text) - CInt(item2.SubItems(0).Text))
            Else
                Return -Math.Sign(CInt(item1.SubItems(0).Text) - CInt(item2.SubItems(0).Text))
            End If

        End Function

    End Class

    Class SumSorter          'sorts on the second column based on the sum of the digits

        Implements IComparer

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

            Dim item1 As ListViewItem = x
            Dim item2 As ListViewItem = y

            Dim sum1 As Integer = 0
            Dim sum2 As Integer = 0

            For Each ch As Char In item1.SubItems(1).Text.ToCharArray
                sum1 += Val(ch)
            Next

            For Each ch As Char In item2.SubItems(1).Text.ToCharArray
                sum2 += Val(ch)
            Next

            If item1.ListView.Sorting = SortOrder.Ascending Then
                Return Math.Sign(sum1 - sum2)
            Else
                Return -Math.Sign(sum1 - sum2)
            End If

        End Function

    End Class

    Class NameSorter         'sorts on the two columns given in the constructor

        Implements IComparer

        Private _columns() As Integer

        Public Sub New(column1 As Integer, column2 As Integer)
            _columns = {column1, column2}
        End Sub

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

            Dim item1 As ListViewItem = x
            Dim item2 As ListViewItem = y

            Dim text1 As String = item1.SubItems(_columns(0)).Text & item1.SubItems(_columns(1)).Text
            Dim text2 As String = item2.SubItems(_columns(0)).Text & item2.SubItems(_columns(1)).Text

            If item1.ListView.Sorting = SortOrder.Ascending Then
                Return StrComp(text1, text2)
            Else
                Return -StrComp(text1, text2)
            End If

        End Function

    End Class

End Class

Computer languages in which I have developed applications

Assembler (DEC, Data General, 8080, GE, SEL, IBM 360)
WATFOR (Waterloo FORTRAN)
FORTRAN (SEL)
APL (IBM 360, IBM VSAPL)
PL/1
C/C++
Borland Paradox
VB.net
vbScript

1
Contributor
0
Replies
21
Views
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.