DataGridView.DataSource скармливается объект типа List<MyT>. Отображается нормально, но сортировка не работает (если скармливать DataTable то работает, т.е. проблема именно в этом). При насильной сортировки — DataGridView.Sort(...) вываливается InvalidOperationException "DataGridView control cannot be sorted if it is bound to an IBindingList that does not support sorting". При замене List<MyT> на BindingList<MyT> (лист с встроенной реализацией IBindingList, находится в System.ComponentModel) происходит тоже самое и тот же exception.
Как добится сортировки если в DataSource должен хранится обект типа List<MyT>?
Здравствуйте, wolandr, Вы писали:
W>DataGridView.DataSource скармливается объект типа List<MyT>. Отображается нормально, но сортировка не работает (если скармливать DataTable то работает, т.е. проблема именно в этом). При насильной сортировки — DataGridView.Sort(...) вываливается InvalidOperationException "DataGridView control cannot be sorted if it is bound to an IBindingList that does not support sorting". При замене List<MyT> на BindingList<MyT> (лист с встроенной реализацией IBindingList, находится в System.ComponentModel) происходит тоже самое и тот же exception.
W>Как добится сортировки если в DataSource должен хранится обект типа List<MyT>?
Погугли SortableBindingList.
public class SortableBindingList<T> : BindingList<T>
{
private PropertyDescriptor _sortProp = null;
private ListSortDirection _sortDir = ListSortDirection.Ascending;
public SortableBindingList()
{
}
public void ApplySort(string propertyName, ListSortDirection direction)
{
PropertyDescriptor property = TypeDescriptor.GetProperties(typeof(T))[propertyName];
ApplySortCore(property, direction);
}
public void AddRange(IEnumerable<T> items)
{
((List<T>)this.Items).AddRange(items);
Sort();
}
protected override bool SupportsSortingCore
{
get { return true; }
}
protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
{
_sortProp = property;
_sortDir = direction;
Sort();
}
public void Sort()
{
if (_sortProp != null)
{
PropertyComparer<T> pc = new PropertyComparer<T>(_sortProp, _sortDir);
((List<T>)this.Items).Sort(pc);
}
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
protected override bool IsSortedCore
{
get { return _sortProp != null; }
}
protected override void RemoveSortCore()
{
// can't unsort
}
protected override PropertyDescriptor SortPropertyCore
{
get { return _sortProp; }
}
protected override ListSortDirection SortDirectionCore
{
get { return _sortDir; }
}
#region PropertyComparer
public class PropertyComparer<TT> : System.Collections.Generic.IComparer<TT>
{
private PropertyDescriptor _property;
private ListSortDirection _direction;
public PropertyComparer(PropertyDescriptor property, ListSortDirection direction)
{
_property = property;
_direction = direction;
}
#region IComparer<T>
public int Compare(TT xWord, TT yWord)
{
// Get property values
object xValue = GetPropertyValue(xWord, _property.Name);
object yValue = GetPropertyValue(yWord, _property.Name);
// Determine sort order
if (_direction == ListSortDirection.Ascending)
{
return CompareAscending(xValue, yValue);
}
else
{
return CompareDescending(xValue, yValue);
}
}
public bool Equals(TT xWord, TT yWord)
{
return xWord.Equals(yWord);
}
public int GetHashCode(TT obj)
{
return obj.GetHashCode();
}
#endregion
// Compare two property values of any type
private int CompareAscending(object xValue, object yValue)
{
int result;
if (xValue is IComparable)
{
// If values implement IComparer
result = ((IComparable)xValue).CompareTo(yValue);
}
else if (xValue.Equals(yValue))
{
// If values don't implement IComparer but are equivalent
result = 0;
}
else
{
// Values don't implement IComparer and are not equivalent, so compare as string values
result = xValue.ToString().CompareTo(yValue.ToString());
}
// Return result
return result;
}
private int CompareDescending(object xValue, object yValue)
{
// Return result adjusted for ascending or descending sort order ie
// multiplied by 1 for ascending or -1 for descending
return CompareAscending(xValue, yValue) * -1;
}
private object GetPropertyValue(TT value, string property)
{
// Get property
PropertyInfo propertyInfo = value.GetType().GetProperty(property);
// Return value
return propertyInfo.GetValue(value, null);
}
}
#endregion
}