我有一个包含多列的ListView。我使用了Microsoft Method to sort my 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 code,因为它会将帖子聚集在一起。我提供了彻底解释它的链接。
答案 0 :(得分:1)
方法#1:Natural Comparer的代码片段整个源代码为here
这将按照您在问题中描述的方式进行排序,同时支持罗马值('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:简单,定制的Comparer(没有罗马值)
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;
}
}
答案 1 :(得分:1)
这是另一种方式。在您的Sort代码中,当您调用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”。
更新:
正常字符串将在没有填充的情况下进行排序。