I have a DataGridView bound to a BindingSource, which is in turn bound to a custom implementation of IBindingList that provides sorting. My DataGridView columns are set to support Automatic sorting. The behavior I would expect is that the first time I click on a column header, the list will be sorted by the corresponding column (subject to my ApplySortCore logic) in the ascending direction and the sort direction icon will appear indicating an ascending direction. I would expect that a second click would result in a descending search and the direction icon to switch reflecting the new direction.
What is happening is that the first time I click a column, the list is sorted in the ascending direction by that column, but the sort direction icon does not appear. The second time I click the column header, an ascending sort is again requested (confirmed with a breakpoint in ApplySortCore), and the ascending sort direction icon appears in the column header. The third time I click the column header, a descending sort is requested, but the ascending sort icon still appears in the column header. The fourth time I click, another descending sort is requested and the descending sort icon appears. The cycle continues such that the actual sort direction changes every other click and the sort direction icon lags the actual sort direction change by one click.
It seems like the DataGridView (or the BindingSource) is not correctly keeping track of the sort direction and is thus incorrectly requesting sorts of the IBindingList ApplySortCore method.
The IBindingList implementation I am using is descended from this abstract class:
internal abstract class CustomSortableBindingList<T> : BindingList<T>
{
private bool m_isSorted;
private ListSortDirection m_sortDirection;
private PropertyDescriptor m_sortProperty;
private IComparer<T> m_currentComparer;
protected CustomSortableBindingList()
{
}
protected CustomSortableBindingList(IList<T> items)
: base(items)
{
}
protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
{
var comparer = GetComparer(property, direction);
Sort(comparer);
m_sortDirection = direction;
m_sortProperty = property;
CurrentComparer = comparer;
}
protected abstract IComparer<T> GetComparer(PropertyDescriptor property, ListSortDirection direction);
protected override void RemoveSortCore()
{
m_isSorted = false;
}
protected override bool SupportsSortingCore
{
get { return true; }
}
protected override bool IsSortedCore
{
开发者_Go百科get { return m_isSorted; }
}
protected override ListSortDirection SortDirectionCore
{
get { return m_sortDirection; }
}
protected override PropertyDescriptor SortPropertyCore
{
get { return m_sortProperty; }
}
public IComparer<T> CurrentComparer
{
get { return m_currentComparer; }
set { m_currentComparer = value; }
}
public void Sort(IComparer<T> comparer)
{
var items = Items as List<T>;
if ((null != items) && (null != comparer))
{
items.Sort(comparer);
m_isSorted = true;
CurrentComparer = comparer;
}
else
{
m_isSorted = false;
}
// Let bound controls know they should refresh their views
OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
}
}
The GetComparer() method of the concrete class simply contains a switch statement based on the name specified in the property descriptor, returning the correct IComparer:
protected override IComparer<HostListItem> GetComparer(PropertyDescriptor property, ListSortDirection direction)
{
switch (property.Name)
{
case "SomeProperty":
return new SomePropertyComparer(direction, CurrentComparer);
default:
return null;
}
}
The CurrentComparer property is used to support a nested sort.
I've tried binding the DataGridView directly to the IBindingList (cutting out the BindingSource, since it doesn't seem like it's really providing any additional functionality), but nothing changes.
Does anybody have any idea why the DataGridView seems to be failing to display the correct sort direction icons or to provide the correct sort direction to the sort calls?
Yep,
The issue there is that you fired the ListChanged event after the sort was completed, which would reset the sort order.
精彩评论