DataView.Sort – 不仅仅是asc / desc(需要自定义排序)

我有一个从数据集构建的报告。 数据集使用Sort属性对数据进行排序。 我知道我可以创建一个这样的排序表达式:

“field desc,field2 asc”

但我现在需要的是一种自定义排序的方法。 在SQL中,我可以通过执行以下操作来执行自定义排序:

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

基本上重新定义我的排序(即,某些值出现在另一个值之前)。

是否可以对DataView执行类似于排序表达式的操作?

好的,我只是快速地将其打开,并没有完成所有必要的error handling和空检查,但它应该给你一个想法,应该足以让你开始:

 public static class DataTableExtensions { public static DataView ApplySort(this DataTable table, Comparison comparison) { DataTable clone = table.Clone(); List rows = new List(); 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大于。

我喜欢BFree的答案,虽然我担心我的代码最终会更新克隆表而不是真正的代码的风险。 (如果你只是在DataView使用扩展方法,我还没有想过要知道这是否真的是一个问题。)

您可以在原始DataTable上执行此操作,方法是向其添加计算的DataColumn (使用Expression属性),然后对其值进行排序。

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

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

首先对AnotherValue进行排序, AnotherValue进行排序,以及之后的所有其他排序。

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

这是实现IComparable的Versioning类:

 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)); } } 

当您将列添加到表中时,不是将Version添加为字符串,而是将其添加为Versioning类:

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

然后正常排序:

 _view.Sort = "Version"; 

我不这么认为。 但是,您可以更改SQL以返回作为case语句结果的“CustomSort”列:

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

您可以使用if或switch语句来获得与select case语句类似的function:

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

要么

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