VB2005 - Listview Column Sort

I'm having a problem that is cited fairly commonly on the net. I've tried various solutions and all of them have the same problem.

I'm trying to do a column sort. String variables sort nicely. However variables that are integer variables don't sort at all. The order is very messed up. There is some sorting but not based in the full magnitude of the sorted integers.

Can anyone help me with this. I've tried several ways of doing this, beginning with MSDN examples and they all have the same failing.

[510 byte] By [ReneeC] at [2007-12-16]
# 1
can you post your code, because mine sort just fine in C#
wacko at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 2

I got it....

And a little while later, I'll be happy to post it !

This is my first managed code project and I must admit, I'm impressed with vb2005 in everything except performance.

ReneeC at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 3
sure why not post it for those who could find it useful
wacko at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 4
OK.... I got most of this off the net and have modified it. It's very stable and works really well.
This sort works on Numeric, Alphanumeric and Data formats.

You have to declare the datatype in column headers like so:

With lvPrView

.View = View.Details

' Add a column with width 20 and left alignment

.Columns.Add("Process", 150, HorizontalAlignment.Center)

.Columns(0).Tag = "String"

.Columns.Add("Pid", 45, HorizontalAlignment.Right)

.Columns(1).Tag = "Numeric"

.Columns.Add("% CPU", 50, HorizontalAlignment.Center)

.Columns(2).Tag = "Numeric"

.Columns.Add("File Name", 500, HorizontalAlignment.Left)

.Columns(6).Tag = "String"

End With


The sort code occurs in a routine and a separate class...

The routine associated with a column click....

Private Sub lvPrView_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles lvPrView.ColumnClick

'Sort when a Column Header is Clicked

Dim SortOrder As SortOrder

Static LastSortColumn As Integer = -1

Static LastSortOrder As SortOrder = SortOrder.Ascending

If LastSortColumn = e.Column Then

If LastSortOrder = SortOrder.Ascending Then

SortOrder = SortOrder.Descending

Else

SortOrder = SortOrder.Ascending

End If

Else

SortOrder = SortOrder.Ascending

End If

Select Case lvPrView.Columns(e.Column).Tag

Case "Numeric"

lvPrView.ListViewItemSorter = New ListViewNumericSort(e.Column, SortOrder)

Case "String"

lvPrView.ListViewItemSorter = New ListViewStringSort(e.Column, SortOrder)

Case "Date"

lvPrView.ListViewItemSorter = New ListViewDateSort(e.Column, SortOrder)

End Select

LastSortColumn = e.Column

LastSortOrder = SortOrder

lvPrView.ListViewItemSorter = Nothing

End Sub


And then the class module.....

Imports System.Collections

Imports System.Windows.Forms

Public Enum SortOrder

Ascending

Descending

End Enum

Public Class ListViewDateSort

Implements IComparer

Private mSortColumn As Integer

Private mSortOrder As SortOrder

Public Sub New(ByVal sortColumn As Integer, ByVal sortOrder As SortOrder)

mSortColumn = sortColumn

mSortOrder = sortOrder

End Sub

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

Dim Result As Integer

Dim ItemX As ListViewItem

Dim ItemY As ListViewItem

ItemX = CType(x, ListViewItem)

ItemY = CType(y, ListViewItem)

If mSortColumn = 0 Then

Result = DateTime.Compare(CType(ItemX.Text, DateTime), CType(ItemY.Text, DateTime))

Else

Result = DateTime.Compare(CType(ItemX.SubItems(mSortColumn).Text, DateTime), CType(ItemY.SubItems(mSortColumn).Text, DateTime))

End If

If mSortOrder = SortOrder.Descending Then

Result = -Result

End If

Return Result

End Function

End Class

Public Class ListViewStringSort

Implements IComparer

Private mSortColumn As Integer

Private mSortOrder As SortOrder

Public Sub New(ByVal sortColumn As Integer, ByVal sortOrder As SortOrder)

mSortColumn = sortColumn

mSortOrder = sortOrder

End Sub

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

Dim Result As Integer

Dim ItemX As ListViewItem

Dim ItemY As ListViewItem

ItemX = CType(x, ListViewItem)

ItemY = CType(y, ListViewItem)

If mSortColumn = 0 Then

Result = ItemX.Text.CompareTo(ItemY.Text)

Else

Result = ItemX.SubItems(mSortColumn).Text.CompareTo(ItemY.SubItems(mSortColumn).Text)

End If

If mSortOrder = SortOrder.Descending Then

Result = -Result

End If

Return Result

End Function

End Class

Public Class ListViewNumericSort

Implements IComparer

Private mSortColumn As Integer

Private mSortOrder As SortOrder


Public
Sub New(ByVal sortColumn As Integer, ByVal sortOrder As SortOrder)

mSortColumn = sortColumn

mSortOrder = sortOrder

End Sub

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

Dim Result As Integer

Dim ItemX As ListViewItem

Dim ItemY As ListViewItem

ItemX = CType(x, ListViewItem)

ItemY = CType(y, ListViewItem)

If mSortColumn = 0 Then

Result = Decimal.Compare(CType(ItemX.Text, Decimal), CType(ItemY.Text, Decimal))

Else

Result = Decimal.Compare(CType(ItemX.SubItems(mSortColumn).Text, Decimal), CType(ItemY.SubItems(mSortColumn).Text, Decimal))

End If

If mSortOrder = SortOrder.Descending Then

Result = -Result

End If

Return Result

End Function

End Class

ReneeC at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 5
Hi!

I found the following code block at:

http://msdn.microsoft.com/library/spa/default.asp?url=/library/SPA/cpref/html/frlrfSystemWindowsFormsListViewClassListViewItemSorterTopic.asp

Code:

' ColumnClick event handler.

Private Sub ColumnClick(ByVal o As Object, ByVal e As ColumnClickEventArgs)

' Set the ListViewItemSorter property to a new ListViewItemComparer
' object. Setting this property immediately sorts the
' ListView using the ListViewItemComparer object.

Me.listView1.ListViewItemSorter = New ListViewItemComparer(e.Column)

End Sub

But i can't load the ListViewItemComparer function bacause y cannot find it.

Do you have any idea?

*************************
19:15

Wait....

Here is the url of the ListViewItemComparer Class

http://msdn2.microsoft.com/library/yw988w73(en-us,vs.80).aspx

And thi is the code:

' Implements the manual sorting of items by columns.
Class ListViewItemComparer
Implements IComparer

Private col As Integer

Public Sub New()
col = 0
End Sub

Public Sub New(ByVal column As Integer)
col = column
End Sub

Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
Implements IComparer.Compare
Return [String].Compare(CType(x, ListViewItem).SubItems(col).Text, CType(y, ListViewItem).SubItems(col).Text)
End Function
End Class

*****************

But i found an error.. when you add items to the listview control and the do a sort by clicking the column and then add items again, the app crashes?

RobertoJimnez at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 6
This application is a personal project, one that I was using to learn VB.Net.

It's a complex application. It's a real time taskmanager that runs continuosly and it frequently adding and deleting items as my system runs programs.

I have never seen it crash and it's received a lot of use especially while I was developing it.

I just tried the scenario you suggested, sorting, starting notepad, sorting, stoping notepad and sorting. The apllication was quite stable and did not flinch.

I could not reproduce the problem in the app.

I don't know whether that's 'good' or 'bad'. :(

I do remember, of course, looking at the Microsoft methods you've broached. As I remember them they didn't work and they didn't sort integer data. They may well have crashed. That's why I looked on the net for an alternative solution. This one really seems to work well.

ReneeC at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 7
I applied the code to VS2003 (w/o using the tag), how come the ColumnClick event is being fired twice when I step through the code (therefore it negates the ascend/decend reversal).
Opteron64 at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 8

I wish I knew a couple of things....

I'm wondering how it works without the tags? Are you only using one datatype?

The other thing I'd wonder was what is firing those events?

I'd take a look at what messages that part of the control is receiving with SPY. I've never seen the behavior you are describing. :(

ReneeC at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...
# 9
Hello,

plz could you tell me how can i get the selected item in a listview (multiselect disabled)? i wanna use it on an other form (form2)...

Atis at 2007-9-8 > top of Msdn Tech,Windows Forms,Windows Forms General...