using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Linq.Expressions; namespace Test { public class SortableBindingList : BindingList { private List originalList; private ListSortDirection sortDirection; private PropertyDescriptor sortProperty; private readonly Action, List> populateBaseList = (a, b) => a.ResetItems(b); private static Dictionary, IEnumerable>> cachedOrderByExpressions = new Dictionary, IEnumerable>>(); public SortableBindingList() { originalList = new List(); } public SortableBindingList(IEnumerable enumerable) { originalList = enumerable.ToList(); populateBaseList(this, originalList); } public SortableBindingList(List list) { originalList = list; populateBaseList(this, originalList); } public void AddRange(IEnumerable itemsToAdd) { foreach (T item in itemsToAdd) { this.Add(item); } } protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) { sortProperty = prop; var orderByMethodName = sortDirection == ListSortDirection.Ascending ? "OrderBy" : "OrderByDescending"; var cacheKey = typeof (T).GUID + prop.Name + orderByMethodName; if (!cachedOrderByExpressions.ContainsKey(cacheKey)) { CreateOrderByMethod(prop, orderByMethodName, cacheKey); } ResetItems(cachedOrderByExpressions[cacheKey](originalList).ToList()); ResetBindings(); sortDirection = sortDirection == ListSortDirection.Ascending ? ListSortDirection.Descending : ListSortDirection.Ascending; } private void CreateOrderByMethod(PropertyDescriptor prop, string orderByMethodName, string cacheKey) { var sourceParameter = Expression.Parameter(typeof (List), "source"); var lambdaParameter = Expression.Parameter(typeof (T), "lambdaParameter"); var accesedMember = typeof (T).GetProperty(prop.Name); var propertySelectorLambda = Expression.Lambda(Expression.MakeMemberAccess(lambdaParameter, accesedMember), lambdaParameter); var orderByMethod = typeof (Enumerable).GetMethods() .Where(a => a.Name == orderByMethodName && a.GetParameters().Length == 2) .Single() .MakeGenericMethod(typeof (T), prop.PropertyType); var orderByExpression = Expression.Lambda, IEnumerable>>( Expression.Call(orderByMethod, new Expression[] { sourceParameter, propertySelectorLambda }), sourceParameter); cachedOrderByExpressions.Add(cacheKey, orderByExpression.Compile()); } protected override void RemoveSortCore() { ResetItems(originalList); } private void ResetItems(List items) { base.ClearItems(); for (int i = 0; i < items.Count; i++) { base.InsertItem(i, items[i]); } } protected override bool SupportsSortingCore { get { return true; } } protected override ListSortDirection SortDirectionCore { get { return sortDirection; } } protected override PropertyDescriptor SortPropertyCore { get { return sortProperty; } } /// /// Diese Methode hat keine Funktion, muss hier aber überschrieben werden, sonst gibt es ein Problem beim laden der Daten aus Threads /// /// protected override void OnListChanged(ListChangedEventArgs e) { } } }