[.Net]实现可排序的BindingList

由于原生的BindingList并未提供排序功能,当DataGridView的数据源设为BindingList时,DataGridView的排序功能将不起使用。

以下是实现排序功能的SortableBindingList,需要用到拓展方法,通过构建表达式树去进行动态排序。

拓展方法如下:

 1 namespace Common
 2 {
 3     public static class Utils
 4     {
 5         /// <summary>
 6         /// 根据类实例的属性名进行排序
 7         /// </summary>
 8         /// <typeparam name="TEntity"></typeparam>
 9         /// <param name="source"></param>
10         /// <param name="orderByProperty">属性名</param>
11         /// <param name="desc">降序:true,默认为升序:false</param>
12         /// <returns></returns>
13         public static IQueryable<TEntity> OrderBy<TEntity>(
14             this IQueryable<TEntity> source, 
15             string orderByProperty,
16             bool desc = false) where TEntity : class
17         {
18             string command = desc ? "OrderByDescending" : "OrderBy";
19             var type = typeof(TEntity);
20             var property = type.GetProperty(orderByProperty) ?? throw new ArgumentException(orderByProperty);
21             var parameter = Expression.Parameter(type, "p");
22             var propertyAccess = Expression.MakeMemberAccess(parameter, property);
23             var orderByExpression = Expression.Lambda(propertyAccess, parameter);
24             var resultExpression = Expression.Call(typeof(Queryable),
25                                                     command,
26                                                     new Type[] {
27                                                         type,
28                                                         property.PropertyType
29                                                     },
30                                                     source.Expression,
31                                                     Expression.Quote(orderByExpression));
32             return source.Provider.CreateQuery<TEntity>(resultExpression);
33         }
34     }
35 }

以下是SortableBindingList的代码:

  1 using System.ComponentModel;
  2  
  3 namespace IIIS_Inglewood.Common
  4 {
  5     /// <summary>
  6     /// 可排序的BindingList
  7     /// </summary>
  8     /// <typeparam name="T">要素类</typeparam>
  9     public class SortableBindingList<T> : BindingList<T>
 10         where T : class
 11     {
 12         /// <summary>
 13         /// 排序完成flag
 14         /// </summary>
 15         private bool isSorted;
 16  
 17         /// <summary>
 18         /// 排序方式
 19         /// </summary>
 20         private ListSortDirection sortDirection = ListSortDirection.Ascending;
 21  
 22         /// <summary>
 23         /// 被排序的属性的相关信息
 24         /// </summary>
 25         private PropertyDescriptor? sortProperty;
 26  
 27         /// <summary>
 28         /// 
 29         /// </summary>
 30         public SortableBindingList()
 31         {
 32         }
 33  
 34         /// <summary>
 35         /// 
 36         /// </summary>
 37         /// <param name="list"></param>
 38         public SortableBindingList(IList<T> list)
 39             : base(list)
 40         {
 41         }
 42  
 43         /// <summary>
 44         /// 是否支持排序(始终支持)
 45         /// </summary>
 46         protected override bool SupportsSortingCore
 47         {
 48             get { return true; }
 49         }
 50  
 51         /// <summary>
 52         /// 排序完成flag
 53         /// </summary>
 54         protected override bool IsSortedCore
 55         {
 56             get { return this.isSorted; }
 57         }
 58  
 59         /// <summary>
 60         /// 排序方式
 61         /// </summary>
 62         protected override ListSortDirection SortDirectionCore
 63         {
 64             get { return this.sortDirection; }
 65         }
 66  
 67         /// <summary>
 68         /// 被排序的属性的相关信息
 69         /// </summary>
 70         protected override PropertyDescriptor? SortPropertyCore
 71         {
 72             get { return this.sortProperty; }
 73         }
 74  
 75         /// <summary>
 76         /// 删除排序信息
 77         /// </summary>
 78         protected override void RemoveSortCore()
 79         {
 80             this.sortDirection = ListSortDirection.Ascending;
 81             this.sortProperty = null;
 82             this.isSorted = false;
 83         }
 84  
 85         /// <summary>
 86         /// 进行排序
 87         /// </summary>
 88         /// <param name="prop">排序项目</param>
 89         /// <param name="direction">排序方式</param>
 90         protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
 91         {
 92             // 记录排序信息
 93             this.sortProperty = prop;
 94             this.sortDirection = direction;
 95  
 96             // 项目一览
 97             var list = Items as List<T>;
 98             if (list == null)
 99             {
100                 return;
101             }
102  
103             // 转成IQueryable,用拓展方法OrderBy进行排序
104             // PS:此处也可以用list.Sort的原生排序方式,但是连续排序多次的话会乱,具体原因暂不清楚
105             var newList = list.AsQueryable().OrderBy(prop.Name, sortDirection == ListSortDirection.Descending).ToList();
106             Items.Clear();
107             newList.ForEach(p => Items.Add(p));
108  
109             // 排序完成
110             this.isSorted = true;
111  
112             // 触发ListChanged事件
113             this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
114         }
115     }
116 }

 

posted on 2024-07-10 17:36  Osiris4Net  阅读(44)  评论(0编辑  收藏  举报

导航