[英]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.