2011-08-18 61 views
4

我有一个DataGridView 6列。DataGridView自定义排序

例子:

column1 column2 column3 column4 column5 column6 
J6   RES-0112G 123.123 456.456 180  1111 
FID2  FIDUCIAL 5.123  -50.005  90   FIDUCIAL 
R100  RES-0113G 1.1  -123.123 90   1111 
C12  CAP-1234H -99.99  -987.123 45   2222 
Q1   CAP-1234Z -99.99  -987.123 45   4444 
J3   RES-0112G 123.123 999.999 0   1111 
FID1  FIDUCIAL 23.123  23.123  0   FIDUCIAL 
F1   CAP-1234 -88.99  -555.111 45   DDDD 
C11  CAP-1234Z -123.99 -123.123 270  abc2222 

而且我想给它一个特殊的排序。比方说,我想最后一个值对它进行排序在这个序列中(第6列)

的Fiducial,1111,2222,DDDD,4444

,然后排序在第二次由第2列阿尔法-numerically。 (注意:abc2222按“2222”而不是“abc”排序)

所以更新的DataGridView是这样的:(对于FIDUCIALS我想用柱1,而不是列进行排序2)

column1 column2 column3 column4 column5 column6 
FID1  FIDUCIAL 23.123  23.123  0   FIDUCIAL 
FID2  FIDUCIAL 5.123  -50.005  90   FIDUCIAL 
J6   RES-0112G 123.123 456.456 180  1111 
J3   RES-0112G 123.123 999.999 0   1111 
R100  RES-0113G 1.1  -123.123 90   1111 
C11  CAP-1234C -123.99 -123.123 270  abc2222 
C12  CAP-1234H -99.99  -987.123 45   2222 
F1   CAP-1234 -88.99  -555.111 45   DDDD 
Q1   CAP-1234Z -99.99  -987.123 45   4444 

有谁知道如何正确地排序呢?我正在使用SortableBindingList<>

+0

你想要在默认情况下进行排序,而用户无法通过单击列标题更改排序顺序,或者实际上是想让用户对“复合”列进行排序或选择它们?另外,SortableBindingList的实现是什么? –

+1

“DDDD”是如何处理的?是什么让它落在“2222”和“4444”之间? –

+0

@Branko:我想将它排序为默认值,以便用户不能更改排序顺序 – theNoobGuy

回答

3

我已经创建了一个示例代码来向您展示技术本身。我希望你不会觉得适应你的需求很复杂。基本思想是按照需求列进行分组,然后在组内应用自定义排序。我没有掌握column6的排序算法,所以我根据您的样本数据进行了简单的排序。希望能帮助到你!

class Program 
{ 
    public class Row 
    { 
     public string Column1 { get; set; } 
     public string Column2 { get; set; } 
     public string Column3 { get; set; } 
     public string Column4 { get; set; } 
     public string Column5 { get; set; } 
     public string Column6 { get; set; } 
    } 

    static void Main(string[] args) 
    { 
     var grid = new [] 
         { 
          new Row { Column1 = "J6", Column2 = "RES-0112G", Column3 = "123.123", Column4 = "456.456", Column5 = "180", Column6 = "1111"}, 
          new Row { Column1 = "FID2", Column2 = "FIDUCIAL", Column3 = "5.123", Column4 = "-50.005", Column5 = "90", Column6 = "FIDUCIAL"}, 
          new Row { Column1 = "R100", Column2 = "RES-0113G", Column3 = "1.1", Column4 = "-123.123", Column5 = "90", Column6 = "1111"}, 
          new Row { Column1 = "C12", Column2 = "CAP-1234H", Column3 = "-99.99", Column4 = "-987.123", Column5 = "45", Column6 = "2222"}, 
          new Row { Column1 = "Q1", Column2 = "CAP-1234Z", Column3 = "-99.99", Column4 = "-987.123", Column5 = "45", Column6 = "4444"}, 
          new Row { Column1 = "J3", Column2 = "RES-0112G", Column3 = "123.123", Column4 = "999.999", Column5 = "0", Column6 = "1111"}, 
          new Row { Column1 = "FID1", Column2 = "FIDUCIAL", Column3 = "23.123", Column4 = "23.123", Column5 = "0", Column6 = "FIDUCIAL"}, 
          new Row { Column1 = "F1", Column2 = "CAP-1234", Column3 = "-88.99", Column4 = "-555.111", Column5 = "45", Column6 = "DDDD"}, 
          new Row { Column1 = "C11", Column2 = "CAP-1234C", Column3 = "-123.99", Column4 = "-123.123", Column5 = "270", Column6 = "abc2222"} 
         }; 

     var result = grid. 
      GroupBy(r => GetSortValue(r.Column6)). 
      OrderBy(g => g.Key, new Column6Comparer()). 
      SelectMany(g => g.OrderBy(r => r, new RowComparer())); 

     foreach (var row in result) 
     { 
      Console.WriteLine("{0,-6}{1,-13}{2,-10}{3,-12}{4,-6}{5,-10}", row.Column1, row.Column2, row.Column3, row.Column4, row.Column5, row.Column6); 
     } 
    } 

    private static string GetSortValue(string source) 
    { 
     Match match = new Regex(@"[\d]+").Match(source); 
     return match.Success ? match.Value : source; 
    } 

    private class Column6Comparer : IComparer<string> 
    { 
     private Dictionary<string, int> ValueToOrder { get; set; } 
     public Column6Comparer() 
     { 
      ValueToOrder = new Dictionary<string, int>(); 
      ValueToOrder["FIDUCIAL"] = 0; 
      ValueToOrder["1111"] = 1; 
      ValueToOrder["2222"] = 2; 
      ValueToOrder["DDDD"] = 3; 
      ValueToOrder["4444"] = 4; 
     } 

     public int Compare(string x, string y) 
     { 
      return ValueToOrder[GetSortValue(x)].CompareTo(ValueToOrder[GetSortValue(y)]); 
     } 

    } 

    private class RowComparer : IComparer<Row> 
    { 
     public int Compare(Row x, Row y) 
     { 
      if (x.Column2 == "FIDUCIAL" && y.Column2 == "FIDUCIAL") 
      { 
       return x.Column1.CompareTo(y.Column1); 
      } 

      if (x.Column2 == "FIDUCIAL" || y.Column2 == "FIDUCIAL") 
      { 
       return x.Column2 == "FIDUCIAL" ? 0 : 1; 
      } 

      return x.Column2.Substring(4).CompareTo(y.Column2.Substring(4)); 
     } 
    } 
} 
1

SortableBindingList对您不利,因为它设计为使用一个属性(列)值对数据进行排序。您必须在添加到绑定列表并禁用排序之前对数据进行排序。您可以使用像这样的比较器对数据进行排序。

public class RowComparer : IComparer<Row> 
    { 
    private List<string> myOrder = new List<string>(new string[] { "FIDUCIAL", "1111", "2222", "DDDD", "4444" }); 

    private int primaryOrder(Row x) 
     { 
     int index = myOrder.FindIndex(v => x.Column6.Contains(v)); 
     return (index >= 0) ? index : myOrder.Count; 
     } 

    public int Compare(Row x, Row y) 
     { 
     int result = primaryOrder(x).CompareTo(primaryOrder(y)); 
     if (result != 0) 
      return result; 

     return x.Column2.CompareTo(y.Column2); 
     } 
    } 

这里写的Comparer的方式,更加灵活:

public class CustomComparer : IComparer<Row> 
     { 
     Predicate<Row>[] myOrder = new Predicate<Row>[] 
     { 
      (row) => row.Column6 == "FIDUCIAL", 
      (row) => row.Column6.Contains("1111") && !row.Column3.Contains("unwanted"), 
      (row) => row.Column6.Contains("2222"), 
      (row) => row.Column6.StartsWith("DDDD"), 
      (row) => row.Column6 == "4444", 
     }; 

     private int primaryOrder(Row row) 
      { 
      for (int i = 0; i < myOrder.Length; i++) 
       { 
       if (myOrder[i](row)) 
        return i; 
       } 
      return myOrder.Length; 
      } 

     public int Compare(Row x, Row y) 
      { 
      int result = primaryOrder(x).CompareTo(primaryOrder(y)); 
      if (result != 0) 
       return result; 

      return x.Column2.CompareTo(y.Column2); 
      } 
     } 
1

这里比较通用的方法,可用于多个类似案例,

public class Row 
    { 
     public string Column1 { get; set; } 
     public string Column2 { get; set; } 
     public string Column3 { get; set; } 
     public string Column4 { get; set; } 
     public string Column5 { get; set; } 
     public string Column6 { get; set; } 
    } 

public interface IComplexSorter<T> : IComparer<T> 
    { 
    } 

public class ComplexSorter<T> : IComplexSorter<T> 
    { 
     private IList<IComplexSorter<T>> _rowSorters; 

     public ComplexSorter() 
     { 
      _rowSorters = new ReadOnlyCollectionBuilder<IComplexSorter<T>>(); 
     } 

     public int Compare(T x, T y) 
     { 
      foreach (var sorter in Sorters) 
      { 
       int value = sorter.Compare(x, y); 
       if (value != 0) 
        return value; 
      } 
      return 0; 
     } 

     public IList<IComplexSorter<T>> Sorters 
     { 
      get { return _rowSorters; } 
     } 
    } 

public class RowColumn1Sorter : IComplexSorter<Row> 
    { 
     public int Compare(Row x, Row y) 
     { 
      if (x.Column6 == "FIDUCIAL" && y.Column6 == "FIDUCIAL") 
       return x.Column1.CompareTo(y.Column1); 

      if (x.Column6 == "FIDUCIAL" || y.Column6 == "FIDUCIAL") 
       return x.Column6 == "FIDUCIAL" ? 0 : 1; 

      return 0; 
     } 
    } 

public class RowColumn2Sorter : IComplexSorter<Row> 
    { 
     public int Compare(Row x, Row y) 
     { 
      return x.Column2.Substring(4).CompareTo(y.Column2.Substring(4)); 
     } 
    } 

public class RowColumn6Sorter : IComplexSorter<Row> 
    { 
     private static IList<string> SortOrder; 

     public RowColumn6Sorter() 
     { 
      SortOrder = new string[] { "FIDUCIAL", "1111", "2222", "DDDD", "4444" }.ToList(); 
     } 

     public int Compare(Row x, Row y) 
     { 
      string xSortValue = SortOrder.Contains(x.Column6) ? x.Column6 : ExtractNumeric(x.Column6); 
      string ySortValue = SortOrder.Contains(y.Column6) ? y.Column6 : ExtractNumeric(y.Column6); 
      int xKey = SortOrder.IndexOf(xSortValue); 
      int yKey = SortOrder.IndexOf(ySortValue); 
      xKey = xKey == -1 ? SortOrder.Count:xKey; 
      yKey = yKey == -1 ? SortOrder.Count:yKey; 
      return xKey - yKey; 
     } 

     private string ExtractNumeric(String value) 
     { 
      Match match = new Regex(@"[\d]+").Match(value); 
      return match.Success ? match.Value : value; 
     } 
    } 

class Program 
    { 
     static void Main(string[] args) 
     { 
      var data = new[] 
      { 
       new Row { Column1 = "J6", Column2 = "RES-0112G", Column3 = "123.123", Column4 = "456.456", Column5 = "180", Column6 = "1111"}, 
       new Row { Column1 = "FID2", Column2 = "FIDUCIAL", Column3 = "5.123", Column4 = "-50.005", Column5 = "90", Column6 = "FIDUCIAL"}, 
       new Row { Column1 = "R100", Column2 = "RES-0113G", Column3 = "1.1", Column4 = "-123.123", Column5 = "90", Column6 = "1111"}, 
       new Row { Column1 = "C12", Column2 = "CAP-1234H", Column3 = "-99.99", Column4 = "-987.123", Column5 = "45", Column6 = "2222"}, 
       new Row { Column1 = "Q1", Column2 = "CAP-1234Z", Column3 = "-99.99", Column4 = "-987.123", Column5 = "45", Column6 = "4444"}, 
       new Row { Column1 = "J3", Column2 = "RES-0112G", Column3 = "123.123", Column4 = "999.999", Column5 = "0", Column6 = "1111"}, 
       new Row { Column1 = "FID1", Column2 = "FIDUCIAL", Column3 = "23.123", Column4 = "23.123", Column5 = "0", Column6 = "FIDUCIAL"}, 
       new Row { Column1 = "F1", Column2 = "CAP-1234", Column3 = "-88.99", Column4 = "-555.111", Column5 = "45", Column6 = "DDDD"}, 
       new Row { Column1 = "C11", Column2 = "CAP-1234C", Column3 = "-123.99", Column4 = "-123.123", Column5 = "270", Column6 = "abc2222"} 
      }.ToList(); 

      ComplexSorter<Row> rowSorter = new ComplexSorter<Row>(); 
      rowSorter.Sorters.Add(new RowColumn6Sorter()); 
      rowSorter.Sorters.Add(new RowColumn1Sorter()); 
      rowSorter.Sorters.Add(new RowColumn2Sorter()); 

      data.Sort(rowSorter); 

      foreach (var row in data) 
      { 
       Console.WriteLine("{0,-6}{1,-13}{2,-10}{3,-12}{4,-6}{5,-10}", row.Column1, row.Column2, row.Column3, row.Column4, row.Column5, row.Column6); 
      } 
      Console.ReadKey(); 
     } 
    }