C# 使用 IComparer 对 x 列进行排序

C# Using IComparer to sort x number of columns

我希望能够按 x 列对数据进行排序,其中 x 不是常数。

上下文:我有一个 DataGridView(未绑定),其中有许多行。因为我想按不止一列排序,所以我创建了一个 class 实现 IComparer 以对网格行进行排序。我已经完成了对单个列进行排序的工作,但是我不确定现在如何更改此 class 以允许对大于 1.

的多个列进行排序

我之前看到的很多答案都提供了对两列或三列进行排序的示例,但是这些似乎是比较 A->B,然后是 B->C 等等。我正在寻找稍微更有活力的东西。

示例:

  1. 用户点击第4列;数据按记录的顺序排序 第 4 列;
  2. 用户然后点击第 6 列;数据按以下顺序排序 第 4 列中的记录然后第 6 列;
  3. 用户点击第2列;数据是 按第 4 列 THEN 第 6 列 THEN 第 2 列中的记录顺序排序;

等等

我目前的情况如下:

public class FormGrid : DataGridView
{
    List<GridSortData> ColIndexSorts = new List<GridSortData>();

    private class GridSortData
    {
        public int ColumnSortIndex;
        public System.Windows.Forms.SortOrder SortOrder;
    }       

    private class GridSort : System.Collections.IComparer
    {
        private static int SortOrder = 1;
        private int SortingColumn;

        public GridSort(System.Windows.Forms.SortOrder sortOrder, int ColumnToSort)
        {
            SortingColumn = ColumnToSort;
            SortOrder = sortOrder == System.Windows.Forms.SortOrder.Ascending ? 1 : -1;
        }

        public int Compare(object x, object y)
        {
            FormGridRow FirstComparable = (FormGridRow)x;
            FormGridRow SecondComparable = (FormGridRow)y;

            int result = 1;

                    result =  FirstComparable.Cells[SortingColumn].Value.ToString().CompareTo(SecondComparable.Cells[SortingColumn].Value.ToString());

            return result * SortOrder;
        }
    }

    private void TSortGrid(int ColIndexToSort, MouseButtons MouseButton)
    {
        GridSortData ColumnToSort = new GridSortData();

        ColumnToSort.ColumnSortIndex = ColIndexToSort;

        if (MouseButton == System.Windows.Forms.MouseButtons.Left)
        {
            ColumnToSort.SortOrder = System.Windows.Forms.SortOrder.Ascending;
        }
        else
        {
            ColumnToSort.SortOrder = System.Windows.Forms.SortOrder.Descending;
        }

        ColIndexSorts.Add(ColumnToSort);

        for (int i = 0; i < ColIndexSorts.Count; i++)
        {
            this.Sort(new GridSort(ColIndexSorts[i].SortOrder, ColIndexSorts[i].ColumnSortIndex));
        }
    }
}

目前这个结果的问题是当你选择了五列后,ColIndexSorts列表中包含了五列排序的数据;但是,由于 for 循环的运行方式,它按升序/降序正确排序,但它仅按列表中的最后排序排序。

我觉得这个问题的解决方案是对要执行的排序列表中的每个排序,记住每次排序后的行顺序,然后对该数据执行额外的排序。

你需要排序稳定。如果您使用的不是,请使用另一个,例如,linq 在 IEnumerable 上提供了一个。我承认这意味着对代码进行相当大的更改,因为您需要在 datagridview 之外进行排序并仅分配结果。顺便说一句,通过字符串表示来比较值对于数字而言远非完美。

编辑

我不知何故忽略了它是未绑定的。如果你想走这条路,你可以这样做:

private class GridSort : System.Collections.IComparer
{
    List<GridSortData> ColIndexSorts = new List<GridSortData>();

    public GridSort(List<GridSortData> ColIndexSorts)
    {
        this.ColIndexSorts = ColIndexSorts;
    }

    public int Compare(object x, object y)
    {
        FormGridRow FirstComparable = (FormGridRow)x;
        FormGridRow SecondComparable = (FormGridRow)y;

        for (int i = 0; i < ColIndexSorts.Count; ++i)
        {
            int index = ColIndexSorts[i].ColumnSortIndex;
            object a = FirstComparable.Cells[index].Value;
            object b = SecondComparable.Cells[index].Value;
            int result = a.ToString().CompareTo(b.ToString());
            if (result != 0)
            {
                if (ColIndexSorts[i].SortOrder == SortOrder.Ascending)
                {
                    return result;
                }
                else
                {
                    return -result;
                }
            }
        }

        return 0;
    }
}

您必须将所有列的 SortMode 设置为程序化并处理 ColumnHeaderMouseClick,但我想您已经知道了。