Results 1 to 9 of 9

Thread: [RESOLVED] sort columns in listview

  1. #1

    Thread Starter
    Member
    Join Date
    Mar 2009
    Posts
    40

    Resolved [RESOLVED] sort columns in listview

    Hi Guys,

    I'm trying to set something up where the user can sort each column by clicking on the header... i've looked at some other examples and they seem pretty longwinded.. just wondering the best way to do this..

    so far i have the below...

    VB Code:
    1. Private Sub resultsListView_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles resultsListView.ColumnClick
    2.         Dim oldsort As SortOrder
    3.         oldsort = resultsListView.Sorting
    4.         If resultsListView.Sorting = SortOrder.Ascending Then
    5.             resultsListView.Sorting = SortOrder.Descending
    6.         ElseIf resultsListView.Sorting = SortOrder.Descending Then
    7.             resultsListView.Sorting = SortOrder.Ascending
    8.         Else : resultsListView.Sorting = SortOrder.Ascending
    9.         End If
    10.         'resultsListView.
    11.         Me.Refresh()
    12.  
    13.     End Sub

    which works fine... but only for the first column in the list view.

    Is there a way of specifying which column to sort based on which is clicked?

    Dan

  2. #2
    PowerPoster stanav's Avatar
    Join Date
    Jul 2006
    Location
    Providence, RI - USA
    Posts
    9,290

    Re: sort columns in listview

    Did you do any search at all? This is the 2nd result returned from Google when searching for the term "listview sort" (the 1st one is the C# version).
    http://msdn.microsoft.com/en-us/kb/kb00319399.aspx
    Let us have faith that right makes might, and in that faith, let us, to the end, dare to do our duty as we understand it.
    - Abraham Lincoln -

  3. #3

    Thread Starter
    Member
    Join Date
    Mar 2009
    Posts
    40

    Re: sort columns in listview

    yeah, i read that..

    I'm asking because that is over 100 lines of code..

    the code I'm currently using is less than 10 and the sort functionality works... ...a bit

    I'm just trying to work out if i can expand what i currently have without using an extra 100 or so lines of someone elses code!

  4. #4
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,423

    Re: sort columns in listview

    how many columns do you have?
    what types of data do the columns contain?

  5. #5
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,423

    Re: sort columns in listview

    try this. its a sorter class that sorts integer,string, or date columns:
    (this is based on a 3 column listview that has a string in column 0, an integer in column 1, and a date in column 2)

    vb Code:
    1. Dim oldsort() As SortOrder = {SortOrder.None, SortOrder.None, SortOrder.None}
    2.  
    3. Private Sub ListView1_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles ListView1.ColumnClick
    4.     If oldsort(e.Column) = SortOrder.Descending Or oldsort(e.Column) = SortOrder.None Then
    5.         oldsort(e.Column) = SortOrder.Ascending
    6.     Else
    7.         oldsort(e.Column) = SortOrder.Descending
    8.     End If
    9.     Dim sorter As New clsListViewItemComparer(e.Column)
    10.     sorter.isDate = e.Column = 2
    11.     sorter.isInteger = e.Column = 1
    12.     sorter.sortOrder = oldsort(e.Column)
    13.     ListView1.ListViewItemSorter = sorter
    14.     ListView1.Sort()
    15.     ListView1.ListViewItemSorter = Nothing
    16. End Sub

    this is the sorter class. you just need to include it in your project + use it as shown above:

    vb Code:
    1. Public Class clsListViewItemComparer
    2.     Implements IComparer
    3.  
    4.     Private _Column As Integer
    5.     Private _isInteger As Boolean = False
    6.     Private _isDate As Boolean = False
    7.     Private _sortOrder As SortOrder = Windows.Forms.SortOrder.None
    8.  
    9.     Public Property Column() As Integer
    10.         Get
    11.             Return _Column
    12.         End Get
    13.         Set(ByVal Value As Integer)
    14.             _Column = Value
    15.         End Set
    16.     End Property
    17.  
    18.     Public Property isInteger() As Boolean
    19.         Get
    20.             Return _isInteger
    21.         End Get
    22.         Set(ByVal Value As Boolean)
    23.             _isInteger = Value
    24.         End Set
    25.     End Property
    26.  
    27.     Public Property isDate() As Boolean
    28.         Get
    29.             Return _isDate
    30.         End Get
    31.         Set(ByVal Value As Boolean)
    32.             _isDate = Value
    33.         End Set
    34.     End Property
    35.  
    36.     Public Property sortOrder() As SortOrder
    37.         Get
    38.             Return _sortOrder
    39.         End Get
    40.         Set(ByVal Value As SortOrder)
    41.             _sortOrder = Value
    42.         End Set
    43.     End Property
    44.  
    45.     Public Sub New(ByVal columnIndex As Integer)
    46.         Column = columnIndex
    47.     End Sub
    48.  
    49.     Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
    50.         Dim ListX As ListViewItem = CType(x, ListViewItem)
    51.         Dim ListY As ListViewItem = CType(y, ListViewItem)
    52.  
    53.         If isInteger Then
    54.             ' Convert column text to numbers before comparing.
    55.             ' If the conversion fails, just use the value 0.
    56.             Dim ListXVal, ListYVal As Decimal
    57.             Try
    58.                 ListXVal = Integer.Parse(ListX.SubItems(Column).Text)
    59.             Catch
    60.                 ListXVal = 0
    61.             End Try
    62.  
    63.             Try
    64.                 ListYVal = Integer.Parse(ListY.SubItems(Column).Text)
    65.             Catch
    66.                 ListYVal = 0
    67.             End Try
    68.  
    69.             If Not sortOrder = Windows.Forms.SortOrder.Ascending Then
    70.                 Return ListYVal.CompareTo(ListXVal)
    71.             Else
    72.                 Return ListXVal.CompareTo(ListYVal)
    73.             End If
    74.  
    75.         ElseIf isDate Then
    76.             Dim ListXVal, ListYVal As Date
    77.             Try
    78.                 ListXVal = Date.Parse(ListX.SubItems(Column).Text)
    79.             Catch
    80.                 'ListXVal = 0
    81.             End Try
    82.  
    83.             Try
    84.                 ListYVal = Date.Parse(ListY.SubItems(Column).Text)
    85.             Catch
    86.                 'ListYVal = 0
    87.             End Try
    88.  
    89.             If Not sortOrder = Windows.Forms.SortOrder.Ascending Then
    90.                 Return Date.Compare(ListYVal, ListXVal)
    91.             Else
    92.                 Return Date.Compare(ListXVal, ListYVal)
    93.             End If
    94.  
    95.         Else
    96.             ' Keep the column text in its native string format
    97.             ' and perform an alphabetic comparison.
    98.             Dim ListXText As String = ListX.SubItems(Column).Text
    99.             Dim ListYText As String = ListY.SubItems(Column).Text
    100.  
    101.             If Not sortOrder = Windows.Forms.SortOrder.Ascending Then
    102.                 Return String.Compare(ListYText, ListXText)
    103.             Else
    104.                 Return String.Compare(ListXText, ListYText)
    105.             End If
    106.  
    107.         End If
    108.  
    109.     End Function
    110. End Class

  6. #6

    Thread Starter
    Member
    Join Date
    Mar 2009
    Posts
    40

    Re: sort columns in listview

    Hi Paul,

    That looks great! it all works awesomely too!

    quick question...

    my first column is IP addresses... when i sort it it does this...
    10.50.200.1
    10.50.200.10
    10.50.20.2
    10.50.200.20

    is this cos im sorting it as a string?

    also, it doesnt like my 4th column... when i click it gets column value as 3 but crashes on:

    vb Code:
    1. If oldsort(e.Column) = SortOrder.Descending Or oldsort(e.Column) = SortOrder.None Then

    that line with "index was outside the bounds of the array"... is this cos its specified as 3 columns as i cant see where ... i would imagine im missing something very obvious!

    Dan

  7. #7

    Thread Starter
    Member
    Join Date
    Mar 2009
    Posts
    40

    Re: sort columns in listview

    D'oh, found how to specify 4 columns. twas obvious. sorry!

    just got the slight issue with sorting the IPs now..

    thanks so much Paul, that's really simple and effective!

    Dan

  8. #8
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,423

    Re: sort columns in listview

    here it is with ipv4 IP Address sorting: (this is a sorter class that sorts integer, decimal, string, IP Address, or date columns. its based on a listview that has a string in column 0, an integer in column 1, a decimal in column 2, a date in column 3, + an ipv4 IP Address in column 4. to use it add the class to your project + use it as shown in the first code box.)

    vb Code:
    1. Dim oldsort() As SortOrder = {SortOrder.None, SortOrder.None, SortOrder.None, SortOrder.None, SortOrder.None}
    2.  
    3. Private Sub ListView1_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles ListView1.ColumnClick
    4.     If oldsort(e.Column) = SortOrder.Descending Or oldsort(e.Column) = SortOrder.None Then
    5.         oldsort(e.Column) = SortOrder.Ascending
    6.     Else
    7.         oldsort(e.Column) = SortOrder.Descending
    8.     End If
    9.     Dim sorter As New clsListViewItemComparer(e.Column)
    10.     sorter.isDate = e.Column = 3
    11.     sorter.isInteger = e.Column = 1
    12.     sorter.isDecimal = e.Column = 2
    13.     sorter.isIPAddress = e.Column = 4
    14.     sorter.sortOrder = oldsort(e.Column)
    15.     ListView1.ListViewItemSorter = sorter
    16.     ListView1.Sort()
    17.     ListView1.ListViewItemSorter = Nothing
    18. End Sub

    vb Code:
    1. Public Class clsListViewItemComparer
    2.     Implements IComparer
    3.  
    4.     Private _Column As Integer
    5.     Private _isInteger As Boolean = False
    6.     Private _isDecimal As Boolean = False
    7.     Private _isDate As Boolean = False
    8.     Private _isIPAddress As Boolean = False
    9.     Private _sortOrder As SortOrder = Windows.Forms.SortOrder.None
    10.  
    11.     Public Property Column() As Integer
    12.         Get
    13.             Return _Column
    14.         End Get
    15.         Set(ByVal Value As Integer)
    16.             _Column = Value
    17.         End Set
    18.     End Property
    19.  
    20.     Public Property isInteger() As Boolean
    21.         Get
    22.             Return _isInteger
    23.         End Get
    24.         Set(ByVal Value As Boolean)
    25.             _isInteger = Value
    26.         End Set
    27.     End Property
    28.  
    29.     Public Property isDecimal() As Boolean
    30.         Get
    31.             Return _isDecimal
    32.         End Get
    33.         Set(ByVal Value As Boolean)
    34.             _isDecimal = Value
    35.         End Set
    36.     End Property
    37.  
    38.     Public Property isDate() As Boolean
    39.         Get
    40.             Return _isDate
    41.         End Get
    42.         Set(ByVal Value As Boolean)
    43.             _isDate = Value
    44.         End Set
    45.     End Property
    46.  
    47.     Public Property isIPAddress() As Boolean
    48.         Get
    49.             Return _isIPAddress
    50.         End Get
    51.         Set(ByVal Value As Boolean)
    52.             _isIPAddress = Value
    53.         End Set
    54.     End Property
    55.  
    56.     Public Property sortOrder() As SortOrder
    57.         Get
    58.             Return _sortOrder
    59.         End Get
    60.         Set(ByVal Value As SortOrder)
    61.             _sortOrder = Value
    62.         End Set
    63.     End Property
    64.  
    65.     Public Sub New(ByVal columnIndex As Integer)
    66.         Column = columnIndex
    67.     End Sub
    68.  
    69.     Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
    70.         Dim ListX As ListViewItem = CType(x, ListViewItem)
    71.         Dim ListY As ListViewItem = CType(y, ListViewItem)
    72.  
    73.         If isInteger Then
    74.             ' Convert column text to numbers before comparing.
    75.             ' If the conversion fails, just use the value 0.
    76.             Dim ListXVal, ListYVal As Integer
    77.             Try
    78.                 ListXVal = Integer.Parse(ListX.SubItems(Column).Text)
    79.             Catch
    80.                 ListXVal = 0
    81.             End Try
    82.  
    83.             Try
    84.                 ListYVal = Integer.Parse(ListY.SubItems(Column).Text)
    85.             Catch
    86.                 ListYVal = 0
    87.             End Try
    88.  
    89.             If Not sortOrder = Windows.Forms.SortOrder.Ascending Then
    90.                 Return ListYVal.CompareTo(ListXVal)
    91.             Else
    92.                 Return ListXVal.CompareTo(ListYVal)
    93.             End If
    94.  
    95.         ElseIf isDecimal Then
    96.             ' Convert column text to numbers before comparing.
    97.             ' If the conversion fails, just use the value 0.
    98.             Dim ListXVal, ListYVal As Decimal
    99.             Try
    100.                 ListXVal = Decimal.Parse(ListX.SubItems(Column).Text)
    101.             Catch
    102.                 ListXVal = 0
    103.             End Try
    104.  
    105.             Try
    106.                 ListYVal = Decimal.Parse(ListY.SubItems(Column).Text)
    107.             Catch
    108.                 ListYVal = 0
    109.             End Try
    110.  
    111.             If Not sortOrder = Windows.Forms.SortOrder.Ascending Then
    112.                 Return Decimal.Compare(ListYVal, ListXVal)
    113.             Else
    114.                 Return Decimal.Compare(ListXVal, ListYVal)
    115.             End If
    116.            
    117.         ElseIf isDate Then
    118.             Dim ListXVal, ListYVal As Date
    119.             Try
    120.                 ListXVal = Date.Parse(ListX.SubItems(Column).Text)
    121.             Catch
    122.                 'ListXVal = 0
    123.             End Try
    124.  
    125.             Try
    126.                 ListYVal = Date.Parse(ListY.SubItems(Column).Text)
    127.             Catch
    128.                 'ListYVal = 0
    129.             End Try
    130.  
    131.             If Not sortOrder = Windows.Forms.SortOrder.Ascending Then
    132.                 Return Date.Compare(ListYVal, ListXVal)
    133.             Else
    134.                 Return Date.Compare(ListXVal, ListYVal)
    135.             End If
    136.         ElseIf isIPAddress Then
    137.             Dim ListXVal, ListYVal As Integer
    138.             Dim splitIndex As Integer = 0
    139.  
    140. nextElement:
    141.  
    142.             Try
    143.                 ListXVal = Integer.Parse(ListX.SubItems(Column).Text.Split("."c)(splitIndex))
    144.             Catch
    145.                 ListXVal = 0
    146.             End Try
    147.  
    148.             Try
    149.                 ListYVal = Integer.Parse(ListY.SubItems(Column).Text.Split("."c)(splitIndex))
    150.             Catch
    151.                 ListYVal = 0
    152.             End Try
    153.  
    154.             If Not sortOrder = Windows.Forms.SortOrder.Ascending Then
    155.                 If ListYVal.CompareTo(ListXVal) = 0 Then
    156.                     If splitIndex < 3 Then
    157.                         splitIndex += 1
    158.                         GoTo nextElement
    159.                     Else
    160.                         Return 0
    161.                     End If
    162.                 Else
    163.                     Return ListYVal.CompareTo(ListXVal)
    164.                 End If
    165.             Else
    166.                 If ListXVal.CompareTo(ListYVal) = 0 Then
    167.                     If splitIndex < 3 Then
    168.                         splitIndex += 1
    169.                         GoTo nextElement
    170.                     Else
    171.                         Return 0
    172.                     End If
    173.                 Else
    174.                     Return ListXVal.CompareTo(ListYVal)
    175.                 End If
    176.             End If
    177.         Else
    178.             ' Keep the column text in its native string format
    179.             ' and perform an alphabetic comparison.
    180.             Dim ListXText As String = ListX.SubItems(Column).Text
    181.             Dim ListYText As String = ListY.SubItems(Column).Text
    182.  
    183.             If Not sortOrder = Windows.Forms.SortOrder.Ascending Then
    184.                 Return String.Compare(ListYText, ListXText)
    185.             Else
    186.                 Return String.Compare(ListXText, ListYText)
    187.             End If
    188.  
    189.         End If
    190.  
    191.     End Function
    192. End Class
    Last edited by .paul.; Apr 20th, 2009 at 11:49 AM.

  9. #9

    Thread Starter
    Member
    Join Date
    Mar 2009
    Posts
    40

    Re: sort columns in listview

    thanks dude..

    That is perfect!

    Dan

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width