[.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) 编辑 收藏 举报