C# .net中PropertyDescriptor的使用和BindingList的ApplySort排序
找了好多资料都是java中PropertyDescriptor的使用,至于C#中的都抄袭别人的,又讲不清楚怎么用。官方文档也没不会手把手教你怎么用,经过一下午的研究,结果如下
1、找到PropertyDescriptor同一dll下的,使用TypeDescriptor反射出属性的PropertyDescriptorCollection ,从这里拿出对应属性的PropertyDescriptor
var myAttribute = TypeDescriptor.GetProperties(_tbNumber)[nameof(_tbNumber.SerialNumber)];
2、就可以使用ApplySort方法了
((IBindingList)listTable).ApplySort(myAttribute,ListSortDirection.Descending);
但是
但是
但是
运行结果报错。也不知道微软是用PropertyDescriptor的哪个属性,我猜测过是使用了Descriptor特性,设置model中的Descriptor也无效。
[Description(nameof(SerialNumber))]
public int SerialNumber { get; set; }
然后查询资料得知了重要的一点,BindList的属性SortPropertyCore默认不开启排序。需要派生类自行实现(我tm出口成小说“¥%……#@&@"省略一万字)

从网上找了实现代码,经过测试修改,如下(来自某论坛2008年的代码),麻烦帮忙艾特下微软把代码加进去:
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;
sortDirection = direction;
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();
}
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 => true;
protected override ListSortDirection SortDirectionCore => sortDirection;
protected override PropertyDescriptor SortPropertyCore => sortProperty;
protected override void OnListChanged(ListChangedEventArgs e)
{
originalList = base.Items.ToList();
base.OnListChanged(e);
}
}
使用
MySortableBindingList<tbNumber> listTable = new MySortableBindingList<tbNumber>();
private void Main_Load(object sender, EventArgs e)
{
dgv.DataSource = listTable;
}
private bool? added(tbNumber _tbNumber)
{
if (listTable.Count > 20)
{
TipCommon.ShowInfoTip("A maximum of 20 can be added");
return false;
}
int c = listTable.Count(a => a.SerialNumber == _tbNumber.SerialNumber);
if (c > 0)
{
TipCommon.ShowInfoTip("This serial number already exists.");
return false;
}
listTable.Add(_tbNumber);
var myAttribute = TypeDescriptor.GetProperties(_tbNumber)[nameof(_tbNumber.SerialNumber)];
((IBindingList)listTable).ApplySort(myAttribute,ListSortDirection.Descending);
return true;
}
private void btnAdd_Click(object sender, EventArgs e)
{
frmNumberForm _frmNumberForm = new frmNumberForm();
_frmNumberForm.added += added;
_frmNumberForm.ShowDialog();
}
作者:兮去博客
出处:https://www.cnblogs.com/bklsj/p/17973010
版权:本文版权归作者和博客园共有
转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任

浙公网安备 33010602011771号