在最近一個項目中,有需求要對頁面中全部的gridview添加排序功能。因爲gridview的數據源綁定的是一個集合類List,而不是DataTable,因此沒法使用DataView排序功能。另外,不一樣的gridview顯示的是不一樣的業務數據,爲了重用代碼只能添加一個泛型方法,使用該方法對數據類型T,按照任意給定的屬性進行排序。因爲是要按照某個不固定的屬性對List內的對象進行排序,因此修改類型T,使之實現IComparable接口,並利用List類的Sort () 方法進行排序是沒法知足需求的。可是List類還提供了另外一個Sort方法,它接受一個IComparer對象做爲參數,在IComparer內能夠實現排序的業務邏輯。惟一須要的就是進行排序的屬性了,而這個在程序的上下文是已知的。
html
思路已經有了,但動手寫代碼前,google了一下相關文章,居然發現有一段功能相似的代碼,惟一不一樣是該該代碼的實現中方法並非泛型的。可是強大的地方是,代碼中對實現的排序支持按照多個屬性排序。因而稍加修改,一段強大的支持按照多屬性對List進行排序的泛型方法就出爐了。
app
首先是表示排序屬性和排序方向的類SortClass,其中保存了排序的屬性和排序的方向。google
/// <summary> /// Class used to hold sort information /// </summary> public class SortClass { private string _sortProperty; public string SortProperty { get { return _sortProperty; } set { _sortProperty = value; } } private SortDirection _sortDirection; public SortDirection SortDirection { get { return _sortDirection; } set { _sortDirection = value; } } public SortClass(string sortProperty, SortDirection sortDirection) { _sortProperty = sortProperty; _sortDirection = sortDirection; }
有了SortClass後就能夠開始實現IComparar接口了。下面是Comparer的代碼,它實現了IComparar接口,包含實際的排序功能。從代碼中能夠看出,Comparer經過遞歸調用CheckSort方法來首先按照多個屬性排序的。spa
/// <summary> /// Implementation of IComparer /// </summary> public class Comparer<T> : IComparer<T> { private List<SortClass> _sortClasses; /// <summary> /// Collection of sorting criteria /// </summary> public List<SortClass> SortClasses { get { return _sortClasses; } } /// <summary> /// Default Constructor /// </summary> public Comparer() { _sortClasses = new List<SortClass>(); } /// <summary> /// Constructor that takes a sorting class collection as param /// </summary> /// <param name="sortClass"> /// Collection of sorting criteria ///</param> public Comparer(List<SortClass> sortClass) { _sortClasses = sortClass; } /// <summary> /// Constructor /// </summary> /// <param name="sortProperty">Property to sort on</param> /// <param name="sortDirection">Direction to sort</param> public Comparer(string sortProperty, SortDirection sortDirection) { _sortClasses = new List<SortClass>(); _sortClasses.Add(new SortClass(sortProperty, sortDirection)); } /// <summary> /// Implementation of IComparer interface to compare to object /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public int Compare(T x, T y) { if (SortClasses.Count == 0) { return 0; } return CheckSort(0, x, y); } /// <summary> /// Recursive function to do sorting /// </summary> /// <param name="sortLevel">Current level sorting at</param> /// <param name="myObject1"></param> /// <param name="myObject2"></param> /// <returns></returns> private int CheckSort(int sortLevel, T myObject1, T myObject2) { int returnVal = 0; if (SortClasses.Count - 1 >= sortLevel) { object valueOf1 = myObject1.GetType().GetProperty(SortClasses[sortLevel].SortProperty).GetValue(myObject1, null); object valueOf2 = myObject2.GetType().GetProperty(SortClasses[sortLevel].SortProperty).GetValue(myObject2, null); if (SortClasses[sortLevel].SortDirection == SortDirection.Ascending) { returnVal = ((IComparable)valueOf1).CompareTo((IComparable)valueOf2); } else { returnVal = ((IComparable)valueOf2).CompareTo((IComparable)valueOf1); } if (returnVal == 0) { returnVal = CheckSort(sortLevel + 1, myObject1, myObject2); } } return returnVal; } }
準備工做完成後,就能夠開始實現真正強大的泛型排序方法了。ListSorter提供了2個靜態方法,一個用來對多個屬性排序,另外一個爲了方便只針對一個屬性進行排序的狀況。 code
public class ListSorter { public static List<T> SortList<T>(List<T> listToSort, List<string> sortExpression, List<SortDirection> sortDirection) { //check parameters if (sortExpression.Count != sortDirection.Count||sortExpression.Count==0||sortDirection.Count==0) { throw new Exception("Invalid sort arguments!"); } //get myComparer Comparer<T> myComparer = new Comparer<T>(); for (int i = 0; i < sortExpression.Count; i++) { SortClass sortClass = new SortClass(sortExpression[i], sortDirection[i]); myComparer.SortClasses.Add(sortClass); } listToSort.Sort(myComparer); return listToSort; } public static List<T> SortList<T>(List<T> listToSort, string sortExpression, SortDirection sortDirection) { //check parameters if (sortExpression == null || sortExpression == string.Empty || sortDirection == null) { return listToSort; } Comparer<T> myComparer = new Comparer<T>(); myComparer.SortClasses.Add(new SortClass(sortExpression, sortDirection)); listToSort.Sort(myComparer); return listToSort; } }
有了上面的代碼,只需簡單幾行就能夠輕鬆實現對泛型List的排序功能了:orm
List<Project> projectList=...; List<Project> sortedProject = ListSorter.SortList(projectList, "Name", SortDirection.Ascending);
出處:http://www.cnblogs.com/dytes/archive/2009/01/06/1370623.htmlxml