.netlinq-to-sqldata-bindingsortingentityset

How do you sort an EntitySet<T>


The MSDN documentation states that an EntitySet implements IBindingList

(see 'Binding to EntitySets' at http://msdn.microsoft.com/en-us/library/bb546190.aspx)

However, it can be clearly seen that an EntitySet does not implement this interface!

So how do I sort?

For context, I'm binding this set to a WPF ListView.

For wider context of problem I'm trying to solve please see this post.


Solution

  • EntitySet<T> doesn't implement IBindingList...it provides a method to get an IBindingList. You need to call .GetNewBindingList() to get an instance of EntitySetBindingList<T>, which derives from SortableBindingList<T>, which is a BindingList<T>. EntitySetBindingList is just a wrapper around the original EntitySet<T> it was created from, so any modifications to it are modifications to the original EntitySet.

    EDIT: Sorting with BindingList:

    To sort with a BindingList, you need to expose some kind of interface to allow sorting. Sorting is supported within the BindingList<T> class, but its through protected properties and methods. It should be possible to expose an expressive sort method with a wrapper:

    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);
        }
    }
    

    You should then be able to sort like so:

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

    There might be additional implementation for the EntitySetBindingWrapper class...such as fortwarding any normally public methods on BindingList<T> to the one provided to the constructor.