Reputation: 22213
I have a custom class that inherits from BindingList(T) that I am binding to a DataGrid.
However, the DataGrid is being populated from the top down and I want it populated from the bottom up. So the bottom item is index 0 rather then the top item.
How can I change my BindingList(T) so that the DataGrid reads it in reverse?
Upvotes: 0
Views: 2409
Reputation: 40507
This article on CodeProject.com about implementing sortable BindingList might help you.
It has a nice generic wrapper for binding list that makes it sortable:
public class MySortableBindingList<T> : BindingList<T> {
// reference to the list provided at the time of instantiation
List<T> originalList;
ListSortDirection sortDirection;
PropertyDescriptor sortProperty;
// function that refereshes the contents
// of the base classes collection of elements
Action<MySortableBindingList<T>, List<T>>
populateBaseList = (a, b) => a.ResetItems(b);
// a cache of functions that perform the sorting
// for a given type, property, and sort direction
static Dictionary<string, Func<List<T>, IEnumerable<T>>>
cachedOrderByExpressions = new Dictionary<string, Func<List<T>,
IEnumerable<T>>>();
public MySortableBindingList() {
originalList = new List<T>();
}
public MySortableBindingList(IEnumerable<T> enumerable) {
originalList = enumerable.ToList();
populateBaseList(this, originalList);
}
public MySortableBindingList(List<T> list) {
originalList = list;
populateBaseList(this, originalList);
}
protected override void ApplySortCore(PropertyDescriptor prop,
ListSortDirection direction) {
/*
Look for an appropriate sort method in the cache if not found .
Call CreateOrderByMethod to create one.
Apply it to the original list.
Notify any bound controls that the sort has been applied.
*/
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) {
/*
Create a generic method implementation for IEnumerable<T>.
Cache it.
*/
var sourceParameter = Expression.Parameter(typeof(List<T>), "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<Func<List<T>, IEnumerable<T>>>(
Expression.Call(orderByMethod,
new Expression[] { sourceParameter,
propertySelectorLambda }),
sourceParameter);
cachedOrderByExpressions.Add(cacheKey, orderByExpression.Compile());
}
protected override void RemoveSortCore() {
ResetItems(originalList);
}
private void ResetItems(List<T> items) {
base.ClearItems();
for (int i = 0; i < items.Count; i++) {
base.InsertItem(i, items[i]);
}
}
protected override bool SupportsSortingCore {
get {
// indeed we do
return true;
}
}
protected override ListSortDirection SortDirectionCore {
get {
return sortDirection;
}
}
protected override PropertyDescriptor SortPropertyCore {
get {
return sortProperty;
}
}
protected override void OnListChanged(ListChangedEventArgs e) {
originalList = base.Items.ToList();
}
}
Upvotes: 2
Reputation: 6485
If your list is inheriting from a Collection class, you can use the Insert(0,item) method to insert to the beginning of the list. That way the newest element would appear on the top. Not sure if the BindingList supports this though.
Upvotes: 0
Reputation: 74530
Why not call the ApplySort method on the IBindingList interface implementation on the BindingList<T>
? You can just pass the value of ListSortDirection.Descending for the second parameter and the DataGrid should display the items in reverse order.
Upvotes: 0
Reputation: 10776
Its simple, but you could also populate the binding list in reverse order (unless you have another reason for keeping the current order).
Upvotes: 0