[英]vb.net sorting mixed integer and string column in ListView
我面對着一個非常大的問題(對我來說)。 我找不到任何解決方案。 我的ListView中有四列:
ID = integer
Name = string
Response = boolean
Memory = mixed integer with string (1'000 KB)
在[ColumnClick]之后,我可以“正常”對前3列進行排序(asc / desc),但是當我嘗試對第四列進行排序時,而不是
1 KB / 5 KB / 1'000 KB
我確實收到了以下信息:
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。 但是我不知道怎么做。
對於表單排序:
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
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
進行重新排序。
值得考慮的是在ColumnHeader
添加“ KB”標識,這樣它就不會在文本中反復出現,並且必須被剝離以進行排序。
由於ListView
僅存儲文本 ,因此可能會有其他問題:“ 9 KB”的排序要高於“ 1000 KB”,因為那里沒有整數-它們是數字。 在許多情況下,您可以對包含數字的字符串使用NaturalSort
(“就像資源管理器”一樣),但是由於某種原因,它不喜歡'
數字組分隔符。
這給我們留下了ListViewItemSorter
。 您可能已經有一個用於對第1列和第2列進行排序。還需要更多邏輯才能從KB列中提取實際數值進行排序:
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
。
用法:
myLV.ListViewItemSorter = New ListViewKBItemComparer(e.Column, SortAsc)
myLV.Sort()
e.Column
是ColumnClick
事件的參數; 而SortAsc
是用於表示Asc或Desc的SortOrder
。
是的,您應該使用給定的示例,在進行一些調整之后,刪除數組中的文本。
如果是我懷疑是的字符串數組,則應使用replace方法刪除撇號,但是在將其添加到ListBox之前應替換它們。
您可以通過以下方式做到這一點:
For Each value In FormatNumber
FormatNumber(count) = Replace(value, "'", "")
count +=1
Next
我猜想FormatNumber是一個字符串數組,因此您需要將其轉換為整數。 為此,我只是將示例從第一個回答中復制到此問題。
在上面的For循環之后添加以下代碼行。
Dim intArray = Array.ConvertAll(FormatNumber, Function(str) Int32.Parse(str))
現在,將intArray的每個值排序后添加到列表框中,看是否可行。
我遇到了同樣的問題,似乎沒有答案。 最后,我進行了排序,將每個lv SubItem
轉換為string array
,然后將要排序的值轉換為string
,然后將值轉換為Integer
,設置了升/降方向,如果需要交換,則將每個行打包從string array
到相對的LV subitem
項的項。 這是我使用的代碼。 它非常適合我的應用程序。
Private Sub SortStandings()
'Sorts Records by won/loss Percentage for Year
'Listview Items to be worked with
Dim LVItemX As ListViewItem
Dim LVItemY As ListViewItem
'String Copy of Value to Compare from List View Item
Dim Strx As String
Dim Stry As String
'Integer Value of Value to Compare From List (Cannot Cast LV Value directly to String
Dim XX As Integer
Dim YY As Integer
'Sort Direction Indicator
Dim J As Integer
Dim ITemX(ColLst.Pct) As String
Dim ItemY(ColLst.Pct) As String
Dim Altx As Integer
Dim Alty As Integer
'For each List View Item except the Last one
For x = 0 To lvDisplay.Items.Count - 2
LVItemX = lvDisplay.Items(x)
'Compare it to each lvItem below it
For y = x + 1 To lvDisplay.Items.Count - 1
LVItemY = lvDisplay.Items(y)
'Convert values to Sort to String (Cannot go directly to Integer
Strx = LVItemX.SubItems.Item(ColLst.Pct).Text
Stry = LVItemY.SubItems.Item(ColLst.Pct).Text
'Take Care of Possible Discrepancy in Format
If Strx = "" Then Strx = "0%"
If Stry = "" Then Stry = "0%"
'Convert Strings to Integer
XX = CInt(Microsoft.VisualBasic.Left(Strx, Len(Strx) - 1))
YY = CInt(Microsoft.VisualBasic.Left(Stry, Len(Stry) - 1))
'Set up a tie Breaker Based on as Different Column
Altx = CInt(LVItemX.SubItems.Item(ColLst.YW).Text)
Alty = CInt(LVItemY.SubItems.Item(ColLst.YW).Text)
'Set up Comparison for Descending ( Change > to < for Ascending )
J = 0
If XX < YY Then
J = -1
End If
If XX = YY And Altx < Alty Then
J = -1
End If
'rebuild Both LV Items in New Locations
If J = -1 Then
For n = 0 To ColLst.Pct
ITemX(n) = LVItemX.SubItems.Item(n).Text
ItemY(n) = LVItemY.SubItems.Item(n).Text
Next
For n = 0 To ColLst.Pct
LVItemX.SubItems.Item(n).Text = ItemY(n)
LVItemY.SubItems.Item(n).Text = ITemX(n)
Next
End If
Next
Next
End Sub
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.