2016-02-05 22 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'的同時按多列進行排序,然後在放開並單擊時按照單列排序:-) –