Дело было давно, но возможно не потеряло своей актуальности.
При разработке одного из приложений (WinForms) нужно было организовать сортировку в столбцах DataGridView. Чего было только не перепробовано, но результата не было.
После долгих поисков в Интернете я все же нашел выход.
В блоге одного программиста (к сожалению, не помню ни имени ни адреса) я нашел направление для дальнейшего копания. В блоге был предоставлен и код, так что не все в этом посте моя заслуга.
В блоге одного программиста (к сожалению, не помню ни имени ни адреса) я нашел направление для дальнейшего копания. В блоге был предоставлен и код, так что не все в этом посте моя заслуга.
А направление вот какое. Нужно было организовать свой BindingList<T> с сортировкой. К сожалению, исходного кода, который был в том блоге, у меня не сохранилось. Так что привожу уже свой, доработанный.
В исходном коде я поменял на самом деле не так много.
- /// <summary>
- /// Provides a generic collection that supports data binding and additionally supports sorting.
- /// See http://msdn.microsoft.com/en-us/library/ms993236.aspx
- /// If the elements are IComparable it uses that; otherwise compares the ToString()
- /// </summary>
- /// <typeparam name="T">The type of elements in the list.</typeparam>
- [Serializable]
- public class SortableBindingList<T> : BindingList<T>
- {
- private bool _isSorted;
- private ListSortDirection _sortDirection = ListSortDirection.Ascending;
- private PropertyDescriptor _sortProperty;
- /// <summary>
- /// Gets a value indicating whether the list supports sorting.
- /// </summary>
- protected override bool SupportsSortingCore
- {
- get { return true; }
- }
- /// <summary>
- /// Gets a value indicating whether the list is sorted.
- /// </summary>
- protected override bool IsSortedCore
- {
- get { return _isSorted; }
- }
- /// <summary>
- /// Gets the direction the list is sorted.
- /// </summary>
- protected override ListSortDirection SortDirectionCore
- {
- get { return _sortDirection; }
- }
- /// <summary>
- /// Gets the property descriptor that is used for sorting the list if sorting is implemented in a derived class; otherwise, returns null
- /// </summary>
- protected override PropertyDescriptor SortPropertyCore
- {
- get { return _sortProperty; }
- }
- /// <summary>
- /// Removes any sort applied with ApplySortCore if sorting is implemented
- /// </summary>
- protected override void RemoveSortCore()
- {
- _sortDirection = ListSortDirection.Ascending;
- _sortProperty = null;
- }
- /// <summary>
- /// Sorts the items if overridden in a derived class
- /// </summary>
- /// <param name="prop"></param>
- /// <param name="direction"></param>
- protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
- {
- _sortProperty = prop;
- _sortDirection = direction;
- if (_sortProperty == null) return; //nothing to sort on
- List<T> list = Items as List<T>;
- if (list == null) return;
- list.Sort(delegate(T lhs, T rhs)
- {
- object lhsValue = lhs == null ? null : _sortProperty.GetValue(lhs);
- object rhsValue = rhs == null ? null : _sortProperty.GetValue(rhs);
- int result = 0;
- if (lhsValue == null && rhsValue == null)
- {
- result = 0;
- }
- else if (lhsValue == null)
- {
- result = -1;
- }
- else if (rhsValue == null)
- {
- result = 1;
- }
- else
- {
- if (lhsValue is IComparable)
- {
- result = ((IComparable)lhsValue).CompareTo(rhsValue);
- }
- else if (!lhsValue.Equals(rhsValue))//not comparable, compare ToString
- {
- result = lhsValue.ToString().CompareTo(rhsValue.ToString());
- }
- }
- if (_sortDirection == ListSortDirection.Descending)
- result = -result;
- return result;
- });
- _isSorted = true;
- //fire an event that the list has been changed.
- OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
- }
- public static implicit operator List<T>(SortableBindingList<T> sortableBindingList)
- {
- return sortableBindingList.Items.ToList();
- }
- }
* This source code was highlighted with Source Code Highlighter.
Была ошибка со сравнением. То есть, когда список проводил сравнение своих элементов, то не учитывал, что они могут быть и равны (да, да). Кроме этого я добавил Serializable атрибут. Было и еще что-то, чего я уж не упомню.
Пользоваться этим классом просто. Приведу просто пример, из которого все станет ясно:
Надеюсь, кому-то этот пост сократить время на поиски решения. А может кто-то предложит и другой способ.
- var list = new SortableBindingList<FinanceDocument>
- {
- new FinanceDocument { Number="1D", Date=DateTime.Now },
- new FinanceDocument { Number="3D", Date=DateTime.Now.AddDays(-1) },
- new FinanceDocument { Number="1G", Date=DateTime.Now.AddDays(-4) },
- new FinanceDocument { Number="1H", Date=DateTime.Now },
- new FinanceDocument { Number="4D", Date=DateTime.Now }
- };
- dataGridView.DataSource = new BindingSource { DataSource = list };
* This source code was highlighted with Source Code Highlighter.
Спасибо огромное :) с экономил туеву хучу времени :)
ОтветитьУдалить@Dmitry A. Larin
ОтветитьУдалитьПожалуйста :-)