【问题标题】:How do you sort an EntitySet<T>如何对 EntitySet<T> 进行排序
【发布时间】:2009-05-29 11:30:33
【问题描述】:

MSDN 文档指出 EntitySet 实现了 IBindingList

(请参阅http://msdn.microsoft.com/en-us/library/bb546190.aspx 上的“绑定到实体集”)

但是可以清楚的看到EntitySet没有实现这个接口!

那么我该如何排序呢?

对于上下文,我将此集合绑定到 WPF ListView。

有关我要解决的问题的更广泛背景,请参阅this post

【问题讨论】:

    标签: .net linq-to-sql data-binding sorting entityset


    【解决方案1】:

    EntitySet 没有实现 IBindingList...它提供了一种获取 IBindingList 的方法。您需要调用 .GetNewBindingList() 来获取 EntitySetBindingList 的实例,该实例派生自 SortableBindingList,它是一个 BindingList。 EntitySetBindingList 只是对创建它的原始 EntitySet 的包装,因此对它的任何修改都是对原始 EntitySet 的修改。

    编辑:使用 BindingList 排序:

    要使用 BindingList 进行排序,您需要公开某种接口以允许排序。 BindingList 类支持排序,但它是通过受保护的属性和方法进行的。应该可以使用包装器公开表达性排序方法:

    public class EntitySetBindingWrapper<T>: BindingList<T>
    {
        public EntitySetBindingWrapper(BindingList<T> root) : base(root)
        {
        }
    
        public void Sort(Expression<Func<T, P>> expr, ListSortDirection direction)
        {
            if (expr == null)
                base.RemoveSortCore();
    
            MemberExpression propExpr = expr as MemberExpression;
            if (propExpr == null) throw new ArgumentException("You must provide a property", "expr");
    
            PropertyDescriptorCollection descriptorCol = TypeDescriptor.GetProperties(typeof(T));
            IEnumerable<PropertyDescriptor> descriptors = descriptorCol.Cast<PropertyDescriptor>();
            PropertyDescriptor descriptor = descriptors.First(pd => pd.Name == propExpr.Member.Name);
    
            base.ApplySortCore(descriptor, direction);
        }
    }
    

    然后你应该能够像这样排序:

    var bindingWrapper = new EntitySetBindingWrapper(myEntitySet.GetNewBindingList());
    bindingWrapper.Sort(e => e.MyProperty, ListSortDirection.Ascending);
    
    listView.DataSource = bindingWrapper;
    

    EntitySetBindingWrapper 类可能还有其他实现...例如将 BindingList 上的任何通常公共方法转发给提供给构造函数的方法。

    【讨论】:

    • 谢谢,不过我不确定这是否会让我走上一条黑暗的小巷。如果您阅读了我在问题底部链接到的帖子,那么我可能在数据绑定方面缺少一些东西。
    • 因此,在阅读了其他帖子后,他犯了调用 .ToList() 的错误。绑定源可能正在更新其基础列表,但该列表不是 EntitySet。调用 .ToList 创建一个新的列表对象。 BindingList 支持排序......有点古老的形式......但它必须公开。您需要创建一个 BindingList 包装器,该包装器可以包装 GetNewBindingList() 返回的内容,并公开 SortPropertyCore 和 SortDirectionCore。我将通过示例发布另一个答案。
    • EntitySet 通过委托给您提到的 GetNewBindingList() 来实现 IListSource.GetList() (并缓存 IBindingList 结果)。如果通过 BindingSource 将 EntitySet 绑定到 WinForms DataGridView,则会自动获得列排序支持。我不了解 WPF,但我原以为它会以类似的方式工作。
    • 我想这取决于您是希望用户能够排序,还是只想向用户呈现无法进一步排序的排序列表。如果是后者,那么这将允许您在绑定之前进行排序。
    【解决方案2】:

    OrderByDecending!

    var tags = objContext.Tags;
    gvTester.DataSource = tags.OrderByDescending(x => x.TagID); ;
    gvTester.DataBind();
    

    【讨论】:

      【解决方案3】:

      你能做 .ToList().OrderBy(x=>x.FieldToSortBy) 吗?

      【讨论】:

        【解决方案4】:

        Hainesy - 从您对 Vinny 帖子的评论来看,我认为您错过了他的观点... [我没有直接将此作为您问题的答案,我只是详细说明 Vinny 要澄清的观点任何可能的混淆。]

        考虑这个对象:

        public class Person
        {
            public string FirstName;
            public string MiddleInitial;
            public string LastName;
        
            public DateTime DateOfBirth { get; set; }
        
            public int Age
            {
                get
                {
                    return (int)DateTime.Today.Subtract(DateOfBirth).TotalDays / 365;
                }
            }
        }
        

        现在,假设我有一个名为 People 的 Person 列表

        var people = new List<Person>();
        

        我的名单上有一大堆人。

        var sortedByLastName = people.OrderBy(o => o.LastName);
        var sortedByFirstName = people.OrderBy(o => o.FirstName);
        var sortedByAge = people.OrderBy(o => o.Age);
        var sortedByAgeDesc = people.OrderByDescending(o => o.Age);
        var sortedByLastThenFirst = people.OrderBy(o => o.LastName).ThenBy(o => o.FirstName);
        

        这适用于复杂的对象。如果我们有一些原始类型的列表,比如字符串:

        var strings = new List<string>();
        

        我想根据它们本身对它们进行排序 - 即不是按我的对象的某些属性

        var sorted = strings.OrderBy(s => s);
        

        这将对对象进行排序。如果您对实现了 IComparable 的复杂对象进行排序以按其默认比较器排序,您也可以使用相同的想法。

        EntitySet 可以以类似的方式排序,无论是对于基本类型还是复杂对象。

        【讨论】:

        • 嗨,谢谢......但我的问题的重点是如何找出如何直接对 EntitySet 进行排序。我知道如何对列表进行排序。当我说“这意味着创建另一个属性”时,我并不是指要对 on 进行排序的属性。如果您阅读我在问题底部链接到的帖子,问题会稍微复杂一些。
        猜你喜欢
        • 2017-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-30
        • 1970-01-01
        • 2019-12-13
        • 1970-01-01
        • 2011-06-20
        相关资源
        最近更新 更多