2016-02-05 43 views
2

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

上下文:我有一个DataGridView(unbound),其中有一些行。由于我想按不止一列进行排序,因此我创建了一个实现IComparer的类来排序网格行。我有这个工作分拣单个列但我不确定如何现在改变这个类,以允许排序的列数> 1.

很多我以前看到的答案提供了排序两个或但是这些列似乎是比较A-> B,然后B-> C等等。我正在寻找更有活力的东西。

实施例:

  1. 用户点击第4栏;数据按记录顺序排列在 列4;
  2. 用户然后单击列6;数据在第4列中按照 记录的顺序排列THEN第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循环的运行方式,它正在按正确的升序/降序进行排序,但它只是按列表中的最终排序进行排序。

我觉得这样做的解决方案是在排序列表中的每种排序执行,记住排序后的行顺序,然后对该数据执行额外的排序。

回答

3

你需要稳定的种类。如果您使用的不是,请使用另一个,例如,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,但我想你已经知道了。

+0

我以前考虑过在DataGridView之外进行排序,因为这确实可以在允许值按照'按原样'进行排序的情况下实现更高的效率,但是与此相关的主要问题是控件未被绑定。因此,在排序时,必须对控件外部的数据进行排序,然后清除控件中的所有行并再次添加数据;对于甚至超过几百条记录,这在UI上看起来很可怕。 –

+0

这很好,非常感谢。老实说,我从来没有想过在排序函数本身中有'for'循环;考虑它现在在它外面,只会导致网格只保留它排序的最后一列!还有,你是正确的,所有进入网格的列在声明时都设置为编程排序,并且所有列都在ColumnHeaderMouseClick事件中。我已经对它进行了处理,以便在按住'Shift'的同时按多列进行排序,然后在放开并单击时按照单列排序:-) –