我有一个继承自 BindingList(T)的自定义类,我绑定到 DataGrid 。
然而, DataGrid 正在自上而下填充,我希望它从下往上填充。所以底部项目是索引0而不是顶部项目。
如何更改 BindingList(T),以便 DataGrid 反向读取?
答案 0 :(得分:2)
它有一个很好的绑定列表通用包装器,可以对它进行排序:
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();
}
}
答案 1 :(得分:0)
它很简单,但你也可以按相反的顺序填充绑定列表(除非你有另一个原因要保持当前的顺序)。
答案 2 :(得分:0)
为什么不在BindingList<T>
上的IBindingList接口实现上调用ApplySort方法?您只需为第二个参数传递ListSortDirection.Descending的值,DataGrid就会以相反的顺序显示这些项目。
答案 3 :(得分:0)
如果列表继承自Collection类,则可以使用Insert(0,item)方法插入列表的开头。这样,最新元素将出现在顶部。不确定BindingList是否支持这个。