Hi
I have a ListView control called HSlist on a form which has 3 columns. The adding data seems to work OK, but the sorting is weird to say the least.
Initially, I thought that the list would be sorted on the contents in the first column, so I added to the ListView with the Item containing the data that I wanted the list to be sorted on (numerical). Then I found that the list was being sorted on the second column (strings), so I swapped the adding routine so that the numerical data was now in the second column - the list now was being sorted on the first column (strings).
What I want, is either to be able to dictate which column the list is to be sorted on, or, some other way of sorting on the numerical data column.
Here is what I use to add data to the list:
Dim freddy As New ListViewItem(Name.Text, 0) 'what's the zero for
freddy.SubItems.Add(Score.Text)
freddy.SubItems.Add(Now())
HSlist.Sorting = SortOrder.Descending
HSlist.Items.Add(freddy)

ListView sorting question
Tom_HDi
Leshay....
What Datatype are you using in the listview elements for date
My guess is that you are using a string.... that routine looks as if it's using a decimaltime. (A Double precision number)
That's way it's not working and definitely why I think you should be using a sting sort on that data type....
denisphillips
I'm not sure that I have altered things 'cleanly', but changing the tag to "string" for the date column doesn't crash anymore, and there is some sorting taking place.
Clicking on col 1 header sorts on col 1 - as does clicking on col 2 which sorts on col 2.
However, when clicking on the Date column header (col 3), it is sorting on col 1 (string) instead of column 3 (Date).
Does the date format matter
Also, where, for example, the code has
.Columns(1).Tag = "Numeric" does that insert the quotes also, because the tag field seems to accept either with or without quotes - and does it matter
randito
OK Andreas, thanks again.
There sure is a lot of compexity involved just to sort what amounts to the equivalent of multi dimension array (in my opinion).
Seems to me the ListView methods are lacking a simple sort - I had originally posted thinking that there would be. However, I'll have to bite the bullet and try to understand the Sorting stuff.
snow bear
I am very sorry, my keyboard does not seem to want to cut and paste the links I want. I will not blame the keyboard, I should have seen that the link was incorret. It was for another reply.
http://msdn2.microsoft.com/en-us/library/system.windows.forms.listview.sort.aspx
This is the link, it will explain more what you need to do and hopefully it will cover you question, if not you are more than welcome to post more questions here.
KhurramShahzad
DarksAngel
First of all, I'm as impressed as I can be that you've gotten that far in such a short amount of time. Let me study it a but.....
I can't tell you how hard that was for me when I first did Dot Net.
Try this.... try assigning the column to a string value.... it should still sort. See what happens.
dmkelly10
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
I'd pay a lot of attention to the red.....
dgolds
You will need to do some more work to accomplish what you want. It is all described in the ListView.Sort method msdn article
http://msdn.microsoft.com/vstudio/express/visualcsharp/starterkit/#blackjack
Typically items are sorted using the Sorting property, which sorts items based on the item text. To customize the sort order, you must write a class that implements the IComparer interface and set the ListViewItemSorter property to an object of that class. This is useful, for example, when you want to sort items by subitem text. For more information on performing manual sorting of items, see the example for the ListViewItemSorter property.
GordonW
This article might be intersting for you, a bit old but it should still apply.
http://msdn.microsoft.com/library/default.asp url=/library/en-us/dnwinforms/html/listviewsort.asp
ajsri77
I did a project on this when I began in Dot Net and I learned a lot of things. MANY users had issues and failures with standard Microsoft Techniques. After a lot of research I found this.. and modified it:
There's are a twist to it. In the .Tag property of each column you specifiy the datatype of the column: "Numeric", "String" or "Date".
Imports System.Collections
Imports System.Windows.Forms
Public Class Form1
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'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
End Sub
'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.....
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
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
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
End Class
After having used this and never having seen it hiccup.... I'm really happy I did.
C Joseph
Thanks for the pointer to Sorting (Sort didn't seem to find that).
The link you gave seems to be for C# coding rather than VB, so I didn't download it.
The Sorting/ListViewSorter stuff may invoke more questions from me though :)
Coldfire23230
Hi
Thanks for routine. I can get it to work on 2 of my three columns. Col1 is string, col2 is numeric and the third is date (formatted like this 10/02/1930).
I get a run time error when clicking on the date col header, at the following line:
Result = Decimal.Compare(CType(ItemX.SubItems(mSortColumn).Text, Decimal), CType(ItemY.SubItems(mSortColumn).Text, Decimal))
reporting Conversion from string "04/16/1947" to type 'Decimal' is not valid.
I was using British formatted dates, but when I got the error on the date field I tried American format but that still produces the error.
Perhaps the format is still incorrect Any ideas
Spardeous
Whoa!!!!!!
The good news about the Tag property is that it's an object and you can put anything in it you wish. The bad news about the Tag property is that it's an object and you can put anything in it you wish.
Quotes specify a string datum and that what that code is looking for. Let me look at how the wrong columns could possibly be happening. Yes the quotes matter. Always use the quotes.
atif ahmed
The code snippet your last post looks identical to the code I am trying to use. It seems the same as the full Class you posted earlier - unless you know differently
With my limited understanding, and trying to trace the flow, it definately doesn't like something about casting
ItemX.SubItems(mSortColumn).Text - which equals "09/10/2002" to DateTime type.
or
ItemX.SubItems(mSortColumn).Text = "02/09/2006" to DateTime type.
I tried inserting
Dim xxxx =
CType(ItemX.SubItems(mSortColumn).Text, DateTime)above the offending line, and this caused the same error. Not entirely sure as to the analysis of that fact, except to say - it didn't work :)