[英]How to Sort Listview Columns Containing Strings & Integers?
我有一個包含多個列的ListView。 我已經使用Microsoft方法對ListView Columns進行排序 。 ListView由一個SQL查詢填充,該查詢可正確地將字符串和整數排序在一起( 如下所示的代碼 )。 例如:
字符串和整數排序問題
以下JobNumber
字符串被視為已排序
“ 10”,“ 1”,“ 2”,“ 3”
使用我的SQL查詢,它們將成為
“ 1”,“ 2”,“ 3”,“ 10”
這是我用來正確排序字符串和整數的查詢
SELECT PK_BillHeader, JobNumber, Description
FROM dbo.BillHeaders
ORDER BY Case IsNumeric(JobNumber)
When 1 Then Replicate('0', 50 - Len(JobNumber)) + JobNumber
Else JobNumber
End
這將輸入零,直到獲得我的SQL列的最大長度(50個字符)減去JobNumber
的當前長度。 這樣,所有內容都被視為一個字符串(包括整數),然后可以正確地對其進行整理。
當我單擊ListView列標題(導致對其進行排序)時,它將停止對字符串和整數進行正確排序,就像對SQL查詢所做的那樣。 相反,它將所有內容都排序為一個字符串,該字符串再次復制了我的“ String&Integer ”排序問題……而且,如果我有十進制值( 第二張圖片 ),它會將它們分類得很奇怪( 請參閱我的比較代碼 )
比較代碼
Public Function [Compare](ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
Dim xItem As clsSortWrapper = CType(x, clsSortWrapper)
Dim yItem As clsSortWrapper = CType(y, clsSortWrapper)
Dim xText As String = xItem.sortItem.SubItems(xItem.sortColumn).Text
Dim yText As String = yItem.sortItem.SubItems(yItem.sortColumn).Text
If Decimal.TryParse(xText, vbNull) Then xText = xText.PadLeft(10, "0"c)
If Decimal.TryParse(yText, vbNull) Then yText = yText.PadLeft(10, "0"c)
Return xText.CompareTo(yText) * IIf(Me.ascending, 1, -1)
End Function
有沒有一種更簡單的方法來實現對帶有字符串和整數的ListView進行排序的結果?
注意:
我省略了在此處發布ListView Sort代碼 ,因為它將使該帖子聚集很多。 我提供了詳細解釋它的鏈接。
方法1:Natural Comparer的代碼片段整個源代碼在這里
這將對您在問題中描述的方式進行排序,還支持羅馬值(“ D”,“ X”等)。
int System.Collections.Generic.IComparer<string>.Compare(string string1,
string string2)
{
mParser1.Init(string1);
mParser2.Init(string2);
int result;
do
{
if (mParser1.TokenType == TokenType.Numerical &
mParser2.TokenType == TokenType.Numerical)
// both string1 and string2 are numerical
result = decimal.Compare(mParser1.NumericalValue, mParser2.NumericalValue);
else
result = string.Compare(mParser1.StringValue, mParser2.StringValue);
if (result != 0) return result;
else
{
mParser1.NextToken();
mParser2.NextToken();
}
} while (!(mParser1.TokenType == TokenType.Nothing &
mParser2.TokenType == TokenType.Nothing));
return 0; //identical
}
方法2:簡單,自定義的比較器(無羅馬值)
class MyComparer : IComparer<string>
{
public int Compare(string x, string y)
{
int xVal, yVal;
var xIsNumeric = int.TryParse( x, out xVal );
var yIsNumeric= int.TryParse( y, out yVal );
if (xIsNumeric && yIsNumeric)
return xVal.CompareTo(yVal);
if (!xIsNumeric && !yIsNumeric)
return x.CompareTo(y);
if (xIsNumeric )
return -1;
return 1;
}
}
這是另一種方式。 當您調用CompareTo時,在您的“排序”代碼墊中,帶有0的字符串。
If Integer.TryParse(xText, VBNull) Then
xText = xText.PadLeft(6, "0"c)
End If
If Integer.TryParse(yText, VBNull) Then
yText = yText.PadLeft(6, "0"c)
End If
Return xText.CompareTo(yText) * IIf(Me.ascending, 1, -1)
這樣,“ 11004”將被比較為“ 011004”並出現在“ 110030”之前,但是填充僅用於比較,該值仍將顯示為“ 11004”。
更新:
普通字符串現在將排序而無需填充。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.