在应用程序中使用ORM方法通常会导致出现这样的情景,即您有一组已检索的对象并希望使用DataGridView在表格视图中显示它们。在DataGridViews中显示对象的集合
在我(有限)的经验中,使用自定义BindingList绑定到DataGridView的对象集合导致性能差和排序不满意。我正在寻找这个问题的通用解决方案,以便填充DataGridView并在稍后提取基础对象时很简单。
我将描述一个我找到的很好的解决方案,但我正在寻找替代品。
在应用程序中使用ORM方法通常会导致出现这样的情景,即您有一组已检索的对象并希望使用DataGridView在表格视图中显示它们。在DataGridViews中显示对象的集合
在我(有限)的经验中,使用自定义BindingList绑定到DataGridView的对象集合导致性能差和排序不满意。我正在寻找这个问题的通用解决方案,以便填充DataGridView并在稍后提取基础对象时很简单。
我将描述一个我找到的很好的解决方案,但我正在寻找替代品。
我打算在这个答案前加上声明,说我的经验是在2.0框架域中。较新的框架可能会提供其他解决方案。
下面是一个BindingList派生类,它支持List的双向排序和其他有用的功能。我无法对PropertyComparer排序进行评分。我在一篇文章中发现了这一点,但现在我发现它遍布互联网,所以我不幸引用了原始资料。
另一种选择是BindingListView:http://blw.sourceforge.net。该类允许您创建List集合的视图,就像使用DataTable对象一样,包括定义Filter和Sort的功能。
public class UsefulBindingList<T> : BindingList<T>
{
private bool _isSorted = false;
private ListSortDirection _sortDirection;
private PropertyDescriptor _sortProperty;
protected override bool SupportsSortingCore
{
get { return true; }
}
protected override bool IsSortedCore
{
get { return _isSorted; }
}
protected override ListSortDirection SortDirectionCore
{
get { return _sortDirection; }
}
protected override PropertyDescriptor SortPropertyCore
{
get { return _sortProperty; }
}
public void AddRange(IEnumerable<T> collection)
{
IEnumerator<T> e = collection.GetEnumerator();
while (e.MoveNext())
{
this.Add(e.Current);
}
}
public T Find(Predicate<T> match)
{
List<T> items = this.Items as List<T>;
if (items != null)
return items.Find(match);
else
return default(T);
}
public int FindIndex(Predicate<T> match)
{
List<T> items = this.Items as List<T>;
if (items != null)
return items.FindIndex(match);
else
return -1;
}
public bool Exists(Predicate<T> match)
{
List<T> items = this.Items as List<T>;
return items.Exists(match);
}
public void Sort()
{
List<T> items = this.Items as List<T>;
if (items != null)
items.Sort();
}
public void Sort(Comparison<T> comparison)
{
List<T> items = this.Items as List<T>;
if (items != null)
items.Sort(comparison);
}
public void Sort(IComparer<T> comparer)
{
List<T> items = this.Items as List<T>;
if (items != null)
items.Sort(comparer);
}
protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
_sortProperty = prop;
_sortDirection = direction;
List<T> items = this.Items as List<T>;
if (items != null)
{
PropertyComparer<T> pc = new PropertyComparer<T>(prop, direction);
items.Sort(pc);
_isSorted = true;
}
else
{
_isSorted = false;
}
this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
protected override void RemoveSortCore()
{
_isSorted = false;
}
}
public class PropertyComparer<T> : IComparer<T>
{
private ListSortDirection _sortDirection;
private PropertyDescriptor _property;
public PropertyComparer(PropertyDescriptor property, ListSortDirection direction)
{
_property = property;
_sortDirection = direction;
}
public int Compare(T x, T y)
{
int rv = 0;
object vx = _property.GetValue(x);
object vy = _property.GetValue(y);
rv = System.Collections.Comparer.Default.Compare(vx, vy);
if (_sortDirection == ListSortDirection.Descending)
rv = -rv;
return rv;
}
}
Javier Lozano建议将对象集合转换为DataTable,然后根据需要将DataRows转换回对象。他的解决方案使用反射来使其通用。他甚至发布了code on his blog。我做了一些小的修改,以支持对象中的Nullable类型,这对我来说目前看起来效果很好。