2009-02-24 134 views
12

我有一个从数据集构建的报告。该数据集使用Sort属性对数据进行排序。我知道我可以创造一种表达这样的:DataView.Sort - 不仅仅是asc/desc(需要自定义排序)

“场递减,场2 ASC”

但我现在需要的是一种方法做一个自定义排序。在SQL中,我可以做这样的事情进行自定义排序:

order by 
    case when field = 'Some Value' then 0 end 
    case when field = 'Another Value' then 1 end 

从根本上重新定义我的排序(即,一些价值来之前的另一值)。

是否有可能对DataView做类似的表达式?

回答

15

好吧,我刚刚刮起这件事真正的快,并没有完成所有的neccessary错误处理和零检查,但它应该给你一个想法,应该是enou GH让你开始:

public static class DataTableExtensions 
{ 
    public static DataView ApplySort(this DataTable table, Comparison<DataRow> comparison) 
    { 

     DataTable clone = table.Clone(); 
     List<DataRow> rows = new List<DataRow>(); 
     foreach (DataRow row in table.Rows) 
     { 
      rows.Add(row);  
     } 

     rows.Sort(comparison); 

     foreach (DataRow row in rows) 
     { 
      clone.Rows.Add(row.ItemArray); 
     } 

     return clone.DefaultView; 
    } 


} 

用法:

DataTable table = new DataTable(); 
    table.Columns.Add("IntValue", typeof(int)); 
    table.Columns.Add("StringValue"); 

    table.Rows.Add(11, "Eleven"); 
    table.Rows.Add(14, "Fourteen"); 
    table.Rows.Add(10, "Ten"); 
    table.Rows.Add(12, "Twelve"); 
    table.Rows.Add(13, "Thirteen"); 

//排序的StringValue:

DataView sorted = table.ApplySort((r, r2) => 
     { 
      return ((string)r["StringValue"]).CompareTo(((string)r2["StringValue"])); 
     }); 

结果:

11十一

14十四

10十

13十三

12十二

//排序INTVALUE:

DataView sorted = table.ApplySort((r, r2) => 
      { 
       return ((int)r["IntValue"]).CompareTo(((int)r2["IntValue"])); 
      }); 

结果:

10十

11十一

13十三

12十二

14十四

编辑:它更改为扩展方法。

现在在你的Lambda中(或者你可以创建一个完整的比较方法),你可以做任何你需要的自定义排序逻辑。请记住,-1小于,0等于,1大于。

+5

我欠你一杯啤酒。 – Orestes 2013-02-20 14:50:30

+0

很好的回答。只需要对双向排序进行一些调整,然后将视图重新绑定到网格中。 – tys 2015-04-07 07:31:35

1

我不这么认为。但是你可以改变你的SQL返回一个“CustomSort”列,它是你的case语句的结果:

select 
    (case when f = 'a' then 0 else 1 end) as CustomSort 
from MyTable 
+0

这是可能的解决方案;希望是我不必使用的,因为这意味着要编辑大约20多个报表的SQL。 – bugfixr 2009-02-24 16:18:20

1

你可以使用if或switch语句来获得类似的功能的选择case语句:

  if (Something == "1") 
       MyView.Sort = "Field1 ASC"; 
      else 
       MyView.Sort = "Field2 ASC"; 

OR

  switch (MyProperty) 
      { 
       case 1: 
        MyView.Sort = "Field1 ASC"; 
        break; 
       case 2: 
        MyView.Sort = "Field2 ASC"; 
        break; 
       default: 
        MyView.Sort = "Field3 ASC"; 
        break; 
      } 
15

我喜欢BFree的答案,但我担心我的代码最终会更新克隆表而不是真正的表。通过将计算DataColumn它((我没有经历过它认为足以知道这是实际上是一个问题,如果你只使用扩展方法在DataView

您可以在原来的DataTable做到这一点使用Expression属性),然后对其值进行排序。

在你的情况下,它会是这样的:

DataColumn c = myTable.Columns.Add("Sort", typeof(int)); 
c.Expression = "iif(field='SomeValue', 0, iif(field='AnotherValue', 1, 2))"; 

这种种SomeValue第一,AnotherValue秒,以及其他一切之后。

4

我知道这篇文章有点旧了,但是我通过实现IComparable来解决这个问题。在这个例子中,我想按版本进行排序(格式为0.0.0.0作为字符串)。

这里是版本控制类,它实现了IComparable:

public class Versioning : IComparable { 
    string _version; 

    int _major; 
    public int Major { 
     get { return (_major); } 
     set { _major = value; } 
    } 

    int _minor; 
    public int Minor { 
     get { return (_minor); } 
     set { _minor = value; } 
    } 

    int _beta; 
    public int Beta { 
     get { return (_beta); } 
     set { _beta = value; } 
    } 

    int _alpha; 
    public int Alpha { 
     get { return (_alpha); } 
     set { _alpha = value; } 
    } 

    public Versioning(string version) { 
     _version = version; 

     var splitVersion = SplitVersion(); 
     if (splitVersion.Length < 4) { 
      Major = Minor = Beta = Alpha = 0; 
     } 

     if (!int.TryParse(splitVersion[0], out _major)) _major = 0; 
     if (!int.TryParse(splitVersion[1], out _minor)) _minor = 0; 
     if (!int.TryParse(splitVersion[2], out _beta)) _beta = 0; 
     if (!int.TryParse(splitVersion[3], out _alpha)) _alpha = 0; 
    } 

    string[] SplitVersion() { 
     return (_version.Split('.')); 
    } 

    int GetCompareTo(Versioning versioning) { 
     var greater = -1; 
     var equal = 0; 
     var less = 1; 

     if (Major > versioning.Major) return (greater); 
     if (Major < versioning.Major) return (less); 
     if (Minor > versioning.Minor) return (greater); 
     if (Minor < versioning.Minor) return (less); 
     if (Beta > versioning.Beta) return (greater); 
     if (Beta < versioning.Beta) return (less); 
     if (Alpha > versioning.Alpha) return (greater); 
     if (Alpha < versioning.Alpha) return (less); 

     return (equal); 
    } 

    public int CompareTo(Versioning versioning) { 
     return (GetCompareTo(versioning)); 
    } 

    public override string ToString() { 
     return (_version); 
    } 

    public int CompareTo(object obj) { 
     if (obj == null) return (1); 
     return (GetCompareTo((Versioning)obj)); 
    } 
} 

而当你添加此列,而不是把版本作为一个字符串表,添加它作为版本控制类:

_table.Columns.Add("Version", typeof(Versioning)); 
_view = new View(_table); 

然后排序通常:

_view.Sort = "Version";