简体   繁体   English

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

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

General Information 一般信息

I have a ListView containing multiple columns. 我有一个包含多个列的ListView。 I have used a Microsoft Method to sort my ListView Columns . 我已经使用Microsoft方法对ListView Columns进行排序 The ListView is populated by a SQL Query which correctly sorts Strings and Integers together ( code shown below ). ListView由一个SQL查询填充,该查询可正确地将字符串和整数排序在一起( 如下所示的代码 )。 For Example: 例如:

String & Integer Sorting Problem 字符串和整数排序问题

The following JobNumber strings are considered as sorted 以下JobNumber 字符串被视为已排序

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

Using my SQL Query, they will become 使用我的SQL查询,它们将成为

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


SQL String & Integer Sorter SQL字符串和整数排序器

Here is the Query I use to sort Strings and Integers correctly 这是我用来正确排序字符串和整数的查询

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

This enters zeros until it gets the maximum length of my SQL column (50 chars) minus the JobNumber 's current length. 这将输入零,直到获得我的SQL列的最大长度(50个字符)减去JobNumber的当前长度。 That way, everything is considered as a string (including integers) which can then be sorted out correctly. 这样,所有内容都被视为一个字符串(包括整数),然后可以正确地对其进行整理。


My Problem 我的问题

When I click on the ListView Column Header (causing it to sort), it stops sorting the strings and integers correctly as it did with my SQL query. 当我单击ListView列标题(导致对其进行排序)时,它将停止对字符串和整数进行正确排序,就像对SQL查询所做的那样。 Instead, it sorts everything as a string which replicates my " String & Integer " sort problem once more ... What is more, if I have decimal values ( second picture ), it sorts them out pretty weird ( see my compare code ) 相反,它将所有内容都排序为一个字符串,该字符串再次复制了我的“ String&Integer ”排序问题……而且,如果我有十进制值( 第二张图片 ),它会将它们分类得很奇怪( 请参阅我的比较代码

机器编号字符串和整数问题钱排序

Compare Code 比较代码

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

Is there a simpler way to acheive my result of sorting a ListView with Strings and Integers? 有没有一种更简单的方法来实现对带有字符串和整数的ListView进行排序的结果?


Note: 注意:

I omitted posting the ListView Sort code here because it would've clustered the post quite a bit. 我省略了在此处发布ListView Sort代码 ,因为它将使该帖子聚集很多。 I provided the link which explains it thoroughly. 我提供了详细解释它的链接。

Approach #1: Codesnippet from Natural Comparer Whole source code is here 方法1:Natural Comparer的代码片段整个源代码在这里

This will sort the way you described in your question, also supporting roman values ('D', 'X', etc.). 这将对您在问题中描述的方式进行排序,还支持罗马值(“ 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 
}

Approach #2: Easy, customized Comparer (Without Roman values) 方法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;   
    }
}

Here's another way. 这是另一种方式。 In your Sort code pad the strings with 0's when you call CompareTo. 当您调用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)

This way "11004" will be compared as "011004" and appear before "110030", but the padding is only for comparison, the value will still be displayed as "11004". 这样,“ 11004”将被比较为“ 011004”并出现在“ 110030”之前,但是填充仅用于比较,该值仍将显示为“ 11004”。

UPDATE: 更新:

Normal strings will be sorted without padding now. 普通字符串现在将排序而无需填充。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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