繁体   English   中英

如何对包含字符串和整数的Listview列进行排序?

[英]How to Sort Listview Columns Containing Strings & Integers?

一般信息

我有一个包含多个列的ListView。 我已经使用Microsoft方法对ListView Columns进行排序 ListView由一个SQL查询填充,该查询可正确地将字符串和整数排序在一起( 如下所示的代码 )。 例如:

字符串和整数排序问题

以下JobNumber 字符串被视为已排序

“ 10”,“ 1”,“ 2”,“ 3”

使用我的SQL查询,它们将成为

“ 1”,“ 2”,“ 3”,“ 10”


SQL字符串和整数排序器

这是我用来正确排序字符串和整数的查询

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM