【问题标题】:Natural Sort for DatgridviewDatagridview 的自然排序
【发布时间】:2017-05-05 11:59:58
【问题描述】:

我有一个数据网格,其中有一列允许用户输入可能包含数字的字符串。我制作的列以编程方式排序,另一列自动排序。 我查看了此网站和其他网站上的所有可用信息,但没有发现任何有效的信息,或者在某些情况下我能够知道如何实施。 许多解决方案使用 Icomparer,但很少有专门用于 datagridview。 这是执行 datagridview1.Sort(Column1, ListSortDirection.Ascending); 后的列数据示例

1
140
2b
40
70
7a
9
aa
aa30
aa5
bc
de

我已经使用此站点的解决方案介绍了 MyDatagridHelper 类和相关代码: C#: Custom sort of DataGridView, 但可惜它给出了以下结果

aa
bc
de
aa30
2b
7a
70
1
40
140
9
aa5

所有其他解决方案并非特定于 datagridview。我是自学成才,对编码比较陌生,所以我无法理解其中的代码。我已尽我所能找到共性并剪切和粘贴,但无济于事。 我认为有希望并可能完成工作的一些例子是: https://www.codeproject.com/articles/22517/natural-sort-comparerNatural Sort Order in C#

我实际上需要有关如何实施这些或任何其他可能完成这项工作的解决方案的帮助。 为简单起见,我没有包括第二列,因为它与问题无关。 谢谢

【问题讨论】:

    标签: c# sorting datagridview


    【解决方案1】:

    您链接到的代码项目文章 22517 具有您需要的逻辑,它只需要通过创建 System.Collections.IComparer 而不是 System.Collections.Generic.Comparer 的实现来与 DataGridView 一起使用进行一些调整

    因此,如果您在项目中为自己创建一个新类,如下所示:

    public class NaturalSortComparer : System.Collections.IComparer {
    
        private System.Collections.Generic.Dictionary<string, string[]> table;
    
        public NaturalSortComparer() {
            table = new System.Collections.Generic.Dictionary<string, string[]>();
        }
    
        public void Dispose() {
            table.Clear();
            table = null;
        }
    
        public int Compare(object x, object y) {
            System.Windows.Forms.DataGridViewRow DataGridViewRow1 = (System.Windows.Forms.DataGridViewRow)x;
            System.Windows.Forms.DataGridViewRow DataGridViewRow2 = (System.Windows.Forms.DataGridViewRow)y;
    
            string xStr = DataGridViewRow1.Cells["Column1"].Value.ToString();
            string yStr = DataGridViewRow2.Cells["Column1"].Value.ToString();
    
    
            if (xStr == yStr) {
                return 0;
            }
            string[] x1, y1;
            if (!table.TryGetValue(xStr, out x1)) {
                x1 = System.Text.RegularExpressions.Regex.Split(xStr.Replace(" ", ""), "([0-9]+)");
                table.Add(xStr, x1);
            }
            if (!table.TryGetValue(yStr, out y1)) {
                y1 = System.Text.RegularExpressions.Regex.Split(yStr.Replace(" ", ""), "([0-9]+)");
                table.Add(yStr, y1);
            }
    
            for (int i = 0; i < x1.Length && i < y1.Length; i++) {
                if (x1[i] != y1[i]) {
                    return PartCompare(x1[i], y1[i]);
                }
            }
            if (y1.Length > x1.Length) {
                return 1;
            } else if (x1.Length > y1.Length) {
                return -1;
            } else {
                return 0;
            }
        }
    
        private static int PartCompare(string left, string right) {
            int x, y;
            if (!int.TryParse(left, out x)) {
                return left.CompareTo(right);
            }
    
            if (!int.TryParse(right, out y)) {
                return left.CompareTo(right);
            }
    
            return x.CompareTo(y);
        }
    }
    

    您可以在此处看到,根据您的示例,我已将其硬编码为使用名为“Column1”的列,但您可以将其更改为更具动态性。

    当您对网格进行排序时,您可以传入刚刚创建的此类的新实例,如下所示:

    dataGridView1.Sort(new NaturalSortComparer());
    

    【讨论】:

    • 非常感谢,这让我非常伤心。知道我需要做什么并尝试使用单个参数进行排序,但将两者结合起来就是问题所在。这是一个很大的帮助!但是,我确实有一个空字符串,即“”作为第一个条目。使用这种方法,空单元格最终位于数字条目和字母条目之间的中间。有没有办法进一步调整以使空单元格成为第一个单元格中的第一个条目,然后是数字,然后是字母?我希望这是数据网格的默认条目。
    • 我在 "string yStr = ..." if (xStr == "") { return 0; }
    • 然后将空单元格放在数据网格的顶部或第一行
    • 还注意到代码原样对待小写和大写的方式不同。它将 test20 放在 Test2 之前。如果您转换 xStr 和 yStr .ToLower() 它会按预期工作。前面引用的 codeproject 文章也是如此,我不得不使用它的一个变体来对组合框的列表进行排序。
    • 很抱歉没有回复上述内容,但看起来您已经克服了您发现的问题。很高兴我能帮助解决最初的困惑:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-12
    • 2010-09-30
    • 2010-11-25
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多