vb.net在ListView中排序混合的整数和字符串列 [英] vb.net sorting mixed integer and string column in ListView
问题描述
我(面对我)面对一个非常大的问题.我找不到任何解决方案.我的ListView中有四列:
I faced quiet a really big problem (for me). I cannot find any solution for it. I have four columns in my ListView:
ID = integer
Name = string
Response = boolean
Memory = mixed integer with string (1'000 KB)
在[ColumnClick]之后,我可以正常"对前3列进行排序(asc/desc),但是当我尝试对第4列进行排序时,而不是
After [ColumnClick] I can sort (asc/desc) first 3 columns "normally", but when i am trying to sort the fouth one, instead of
1 KB/5 KB/1'000 KB
我确实收到了这样的信息:
I do receive something like this:
1 KB/1'000 KB/5 KB
第四列是这样打印的:
ListView1.Items(Count).SubItems.Add(FormatNumber(pMem, 0) & " KB")
我正在考虑:
If e.Column.ToString = 3 Then
Dim final As Integer
For Each value In ListView1.Items
Replace(value.SubItems(3), "'", "")
Replace(value.SubItems(3), " KB", "")
final = value
Next
Else
...
然后使用与ID相同的方式对整数进行排序,然后以某种方式将它们放回ListView.但是我不知道怎么办.
Then sort integers same way as ID was, and then put them back, to the ListView somehow. But I cannot figure out how.
用于在表单中排序:
Private Sub ListView1_ColumnClick(sender As Object, e As ColumnClickEventArgs) Handles ListView1.ColumnClick
Dim ListViewSorter As New ListViewSorter
With ListViewSorter
.SortingOrder = 1
.ColumnIndex = e.Column
End With
ListView1.ListViewItemSorter = ListViewSorter
End Sub
还有我的ListViewSorter.vb
And my ListViewSorter.vb
Public Class ListViewSorter
Implements IComparer
Private ColumnId As Integer
Private SortOrder As SortOrder
Private ItemComparer As CaseInsensitiveComparer
Public Sub New()
ColumnId = 0
SortOrder = 0
ItemComparer = New CaseInsensitiveComparer()
End Sub
Public Property ColumnIndex() As Integer
Get
Return ColumnId
End Get
Set(Value As Integer)
ColumnId = Value
End Set
End Property
Public Property SortingOrder() As SortOrder
Get
Return SortOrder
End Get
Set(Value As SortOrder)
SortOrder = Value
End Set
End Property
Public Function Compare(x As Object, y As Object) As Integer Implements IComparer.Compare
Dim myResults As Integer
Dim strX As String = DirectCast(x, ListViewItem).SubItems(ColumnId).Text
Dim strY As String = DirectCast(y, ListViewItem).SubItems(ColumnId).Text
Dim num As Point
If Integer.TryParse(strX, num.X) And Integer.TryParse(strY, num.Y) Then
myResults = ItemComparer.Compare(num.X, num.Y)
Else
myResults = ItemComparer.Compare(strX, strY)
End If
If SortOrder = 1 Then
Return myResults
ElseIf SortOrder = 2 Then
Return -myResults
Else
Return 0
End If
End Function
End Class
推荐答案
最佳解决方案是使用DataGridView
.使用DataSource
,而不是先创建和添加ListViewItems
,然后再添加ListViewSubItems
,您可以用一行代码填充控件.它还使用类型化的列,因此KB或KG的列将像数字一样排序.然后可以使用简单的linq表达式对DataSource
重新排序.
The optimum solution would be to use a DataGridView
. Using a DataSource
, rather than creating and adding ListViewItems
, then ListViewSubItems
, you could populate the control with one line of code. It also uses typed columns, so a column of KBs or KGs would sort like numbers. A simple linq expression could then be used to reorder the DataSource
.
值得考虑的是,在ColumnHeader
中添加"KB"标识,这样它就不会在文本中一遍又一遍地重复,并且必须被剥离以进行排序.
It would be worth considering adding the "KB" designation in the ColumnHeader
so it doesn't repeat over and over in the text and have to be stripped off for sorting.
由于ListView
仅存储文本,因此您可能会遇到其他问题:"9 KB"的排序要比"1000 KB"高,因为那里没有整数-它们是数字.在许多情况下,可以对包含数字的字符串使用NaturalSort
(就像资源管理器"一样),但是由于某种原因,它不喜欢'
数字组分隔符.
Since the ListView
stores only text, you can have other issues: "9 KB" will sort higher than "1000 KB" because there are no integers there - they are numerals. In many cases, you can use a NaturalSort
for strings containing numerals ("just like explorer"), but for whatever reason it didn't like the '
number group separator.
留下ListViewItemSorter
给我们.您可能已经有一个用于对第1列和第2列进行排序.还需要更多逻辑才能从KB列中提取实际数值进行排序:
Which leaves us with a ListViewItemSorter
. You probably already have one for sorting column 1 and 2. A little more logic is needed to extract an actual numeric value from the KB column for sorting:
Public Class ListViewKBItemComparer
Implements IComparer
Private mySortFlipper As Int32 = 1
Public Property SortColumn As Int32 = 0
Public Sub New()
End Sub
Public Sub New(column As Int32, sort As SortOrder)
mySortFlipper = If(sort = SortOrder.Ascending, 1, -1)
SortColumn = column
End Sub
Public Function Compare(x As Object, y As Object) As Integer Implements IComparer.Compare
Dim result As Int32
Dim lvX = CType(x, ListViewItem)
Dim lvY = CType(y, ListViewItem)
If SortColumn = 3 Then
result = KBCompare(lvX, lvY)
Else
result = String.Compare(lvX.SubItems(SortColumn).Text,
lvY.SubItems(SortColumn).Text)
End If
Return (result * mySortFlipper)
End Function
Private Function KBCompare(x As ListViewItem, y As ListViewItem) As Int32
' strip the text
Dim xs = x.SubItems(SortColumn).Text.Replace(" KB", "")
Dim ys = y.SubItems(SortColumn).Text.Replace(" KB", "")
' convert to decimal
Dim decX As Decimal = -1
Decimal.TryParse(xs, decX)
Dim decY As Decimal = -1
Decimal.TryParse(ys, decY)
' return comparison result
Return decX.CompareTo(decY)
End Function
End Class
在某些字符串也可能包含小数的情况下,我使用了Decimal
.如果不是,只需将Decimal
更改为Int32
.
I used Decimal
in case some of the strings could also include fractions. If not, just change Decimal
to Int32
.
用法:
myLV.ListViewItemSorter = New ListViewKBItemComparer(e.Column, SortAsc)
myLV.Sort()
e.Column
是ColumnClick
事件的参数; SortAsc
是SortOrder
表示升序或降序.
e.Column
is a param from the ColumnClick
event; and SortAsc
is a SortOrder
to indicate Asc or Desc.
这篇关于vb.net在ListView中排序混合的整数和字符串列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!