WIP
DirectOutput framework for virtual pinball cabinets WIP
Go to:
Overview 
SortableBindingList.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
4 using System.Linq;
6 
7 namespace DirectOutput.General.Generic
8 {
9  //TODO: CHeck if the class can be dropped.
14  public class SortableBindingList<T> : BindingList<T>
15  {
16 
17  // reference to the list provided at the time of instantiation
18  List<T> originalList;
19  ListSortDirection sortDirection;
20  PropertyDescriptor sortProperty;
21 
22  // function that refereshes the contents
23  // of the base classes collection of elements
24  Action<SortableBindingList<T>, List<T>>
25  populateBaseList = (a, b) => a.ResetItems(b);
26 
27  // a cache of functions that perform the sorting
28  // for a given type, property, and sort direction
29  static Dictionary<string, Func<List<T>, IEnumerable<T>>>
30  cachedOrderByExpressions = new Dictionary<string, Func<List<T>,
31  IEnumerable<T>>>();
32 
34  {
35  originalList = new List<T>();
36  }
37 
38  public SortableBindingList(IEnumerable<T> enumerable)
39  {
40  originalList = enumerable.ToList();
41  populateBaseList(this, originalList);
42  }
43 
44  public SortableBindingList(List<T> list)
45  {
46  originalList = list;
47  populateBaseList(this, originalList);
48  }
49 
50  protected override void ApplySortCore(PropertyDescriptor prop,
51  ListSortDirection direction)
52  {
53  /*
54  Look for an appropriate sort method in the cache if not found .
55  Call CreateOrderByMethod to create one.
56  Apply it to the original list.
57  Notify any bound controls that the sort has been applied.
58  */
59 
60  sortProperty = prop;
61 
62  var orderByMethodName = sortDirection ==
63  ListSortDirection.Ascending ? "OrderBy" : "OrderByDescending";
64  var cacheKey = typeof(T).GUID + prop.Name + orderByMethodName;
65 
66  if (!cachedOrderByExpressions.ContainsKey(cacheKey))
67  {
68  CreateOrderByMethod(prop, orderByMethodName, cacheKey);
69  }
70 
71  ResetItems(cachedOrderByExpressions[cacheKey](originalList).ToList());
72  ResetBindings();
73  sortDirection = sortDirection == ListSortDirection.Ascending ?
74  ListSortDirection.Descending : ListSortDirection.Ascending;
75  }
76 
77 
78  private void CreateOrderByMethod(PropertyDescriptor prop,
79  string orderByMethodName, string cacheKey)
80  {
81 
82  /*
83  Create a generic method implementation for IEnumerable<T>.
84  Cache it.
85  */
86 
87  var sourceParameter = Expression.Parameter(typeof(List<T>), "source");
88  var lambdaParameter = Expression.Parameter(typeof(T), "lambdaParameter");
89  var accesedMember = typeof(T).GetProperty(prop.Name);
90  var propertySelectorLambda =
91  Expression.Lambda(Expression.MakeMemberAccess(lambdaParameter,
92  accesedMember), lambdaParameter);
93  var orderByMethod = typeof(Enumerable).GetMethods()
94  .Where(a => a.Name == orderByMethodName &&
95  a.GetParameters().Length == 2)
96  .Single()
97  .MakeGenericMethod(typeof(T), prop.PropertyType);
98 
99  var orderByExpression = Expression.Lambda<Func<List<T>, IEnumerable<T>>>(
100  Expression.Call(orderByMethod,
101  new Expression[] { sourceParameter,
102  propertySelectorLambda }),
103  sourceParameter);
104 
105  cachedOrderByExpressions.Add(cacheKey, orderByExpression.Compile());
106  }
107 
108  protected override void RemoveSortCore()
109  {
110  ResetItems(originalList);
111  }
112 
113  private void ResetItems(List<T> items)
114  {
115 
116  base.ClearItems();
117 
118  for (int i = 0; i < items.Count; i++)
119  {
120  base.InsertItem(i, items[i]);
121  }
122  }
123 
124  protected override bool SupportsSortingCore
125  {
126  get
127  {
128  // indeed we do
129  return true;
130  }
131  }
132 
133  protected override ListSortDirection SortDirectionCore
134  {
135  get
136  {
137  return sortDirection;
138  }
139  }
140 
141  protected override PropertyDescriptor SortPropertyCore
142  {
143  get
144  {
145  return sortProperty;
146  }
147  }
148 
149  protected override void OnListChanged(ListChangedEventArgs e)
150  {
151  originalList = base.Items.ToList();
152  }
153 
154  }
155 }
override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
Inherits BindingList and overrides the functions necessary to provide sorting. The code of this c...
override void OnListChanged(ListChangedEventArgs e)