[.Net]实现可排序的BindingList

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

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

拓展方法如下:

namespace Common
{
    public static class Utils
    {
        /// <summary>
        /// 根据类实例的属性名进行排序
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="source"></param>
        /// <param name="orderByProperty">属性名</param>
        /// <param name="desc">降序:true,默认为升序:false</param>
        /// <returns></returns>
        public static IQueryable<TEntity> OrderBy<TEntity>(
            this IQueryable<TEntity> source, 
            string orderByProperty,
            bool desc = false) where TEntity : class
        {
            string command = desc ? "OrderByDescending" : "OrderBy";
            var type = typeof(TEntity);
            var property = type.GetProperty(orderByProperty) ?? throw new ArgumentException(orderByProperty);
            var parameter = Expression.Parameter(type, "p");
            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            var orderByExpression = Expression.Lambda(propertyAccess, parameter);
            var resultExpression = Expression.Call(typeof(Queryable),
                                                    command,
                                                    new Type[] {
                                                        type,
                                                        property.PropertyType
                                                    },
                                                    source.Expression,
                                                    Expression.Quote(orderByExpression));
            return source.Provider.CreateQuery<TEntity>(resultExpression);
        }
    }
}

以下是SortableBindingList的代码:

using System.ComponentModel;

namespace IIIS_Inglewood.Common
{
    /// <summary>
    /// 可排序的BindingList
    /// </summary>
    /// <typeparam name="T">要素类</typeparam>
    public class SortableBindingList<T> : BindingList<T>
        where T : class
    {
        /// <summary>
        /// 排序完成flag
        /// </summary>
        private bool isSorted;

        /// <summary>
        /// 排序方式
        /// </summary>
        private ListSortDirection sortDirection = ListSortDirection.Ascending;

        /// <summary>
        /// 被排序的属性的相关信息
        /// </summary>
        private PropertyDescriptor? sortProperty;

        /// <summary>
        /// 
        /// </summary>
        public SortableBindingList()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="list"></param>
        public SortableBindingList(IList<T> list)
            : base(list)
        {
        }

        /// <summary>
        /// 是否支持排序(始终支持)
        /// </summary>
        protected override bool SupportsSortingCore
        {
            get { return true; }
        }

        /// <summary>
        /// 排序完成flag
        /// </summary>
        protected override bool IsSortedCore
        {
            get { return this.isSorted; }
        }

        /// <summary>
        /// 排序方式
        /// </summary>
        protected override ListSortDirection SortDirectionCore
        {
            get { return this.sortDirection; }
        }

        /// <summary>
        /// 被排序的属性的相关信息
        /// </summary>
        protected override PropertyDescriptor? SortPropertyCore
        {
            get { return this.sortProperty; }
        }

        /// <summary>
        /// 删除排序信息
        /// </summary>
        protected override void RemoveSortCore()
        {
            this.sortDirection = ListSortDirection.Ascending;
            this.sortProperty = null;
            this.isSorted = false;
        }

        /// <summary>
        /// 进行排序
        /// </summary>
        /// <param name="prop">排序项目</param>
        /// <param name="direction">排序方式</param>
        protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
        {
            // 记录排序信息
            this.sortProperty = prop;
            this.sortDirection = direction;

            // 项目一览
            var list = Items as List<T>;
            if (list == null)
            {
                return;
            }

            // 转成IQueryable,用拓展方法OrderBy进行排序
            // PS:此处也可以用list.Sort的原生排序方式,但是连续排序多次的话会乱,具体原因暂不清楚
            var newList = list.AsQueryable().OrderBy(prop.Name, sortDirection == ListSortDirection.Descending).ToList();
            Items.Clear();
            newList.ForEach(p => Items.Add(p));

            // 排序完成
            this.isSorted = true;

            // 触发ListChanged事件
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值