2009-02-24 136 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";