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

时间:2013-06-27 19:19:16

标签: c# vb.net listview sorting

一般资料

我有一个包含多列的ListView。我使用了Microsoft Method to sort my ListView Columns。 ListView由SQL查询填充,该查询正确地将字符串和整数排序在一起(代码如下所示)。例如:

字符串&整数排序问题

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

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

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

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


SQL String&整数分拣机

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

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 ”排序问题...更重要的是,如果我有十进制值(第二张图片 ),它排序很奇怪(看我的比较代码

Machine Number String & Integer Problem Money Sort

比较代码

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,因为它会将帖子聚集在一起。我提供了彻底解释它的链接。

2 个答案:

答案 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”。

更新:

正常字符串将在没有填充的情况下进行排序。