我希望能够按 x 列对数据进行排序,其中 x 不是常数。
上下文:我有一个 DataGridView(未绑定(bind)),其中有许多行。由于我想按多个列进行排序,因此我创建了一个实现 IComparer 的类,以便对网格行进行排序。我已经完成了对单个列进行排序的工作,但是我不确定现在如何更改此类以允许对多列> 1 进行排序。
我之前看到的很多答案都提供了对两列或三列进行排序的示例,但是这些似乎是比较 A->B,然后 B->C 等等。我正在寻找稍微更有活力的东西。
示例:
- 用户点击第 4 列;数据按记录顺序排序 第 4 栏;
- 然后用户点击第 6 列;数据按以下顺序排序 第 4 列中的记录然后是第 6 列;
- 用户点击第 2 列;数据是 按第 4 列中的记录顺序排序,然后是第 6 列,然后是第 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 之外进行排序并只分配结果。顺便说一句,通过字符串表示形式比较值对于数字来说远非完美。
编辑
我不知何故忽略了它是未绑定(bind)的。如果你想这样做,你可以这样做:
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,但我想您已经知道了。
关于C# 使用 IComparer 对 x 列进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35214250/