Программная сортировка DataGrid

Эта статья показывает как программно отсортировать System.Windows.Forms.DataGrid. Другими словами, как сэмулировать «щелчок» по заголовку столбца.

Обычно, чтобы отсортировать DataGrid, мы вызываем метод DataView.Sort из DataView. Но что если наш DataGrid связан с заказными данными? В этом случае данный метод применить нельзя!

Подготовка

Как-то я писал приложение, в котором нужно было «запоминать» способ сортировки DataGrid. Мне нужно было сохранить сортировки в реестр и считывать их каждый раз, когда стартует приложение.
Проблема заключалась в том, что мой DataGrid был набором заказных данных, к которым нельзя было применить DataView или DataTable.

Основы сортировки

Если ваш DataGrid связан с некоторой коллекцией IList и вы хотите внедрить в проект поддержку сортировки вашего DataGrid, ваша коллекция должна реализовать интерфейс IBindingList. Этот интерфейс содержит среди своих методов метод ApplySort(). Когда пользователь щелкает по заголовку столбца, DataGrid вызывает метод ApplySort().

Метод ApplySort() принимает два параметра: property и direction.
void IBindingList.ApplySort(PropertyDescriptor property,
ListSortDirection direction)

Каждый столбец вашего DataGrid представляет собой некоторое свойство выделенного объекта. И вы должны пропустить это свойство через метод ApplySort().

Эмуляция нажатия на заголовок столбца

Я выяснил, что простой вызов ApplySort() не работает. Вызов protected-метода DataGrid'а OnMouseDown() с MouseEventArgs, указывающим на заголовок столбца так же не работает!

Итак, Я использовал System.Reflection, чтобы заглянуть поглубже в класс DataGrid и посмотреть, что происходит, когда пользователь щелкает по заголовку. В списке private-членов DataGrid я нашел private-метод ColumnHeaderClicked(). Понятно что я имею ввиду? Бинго.

Этот метод определен следующим образом:
private void ColumnHeaderClicked(PropertyDescriptor prop)

Итак, если мы хотим отсортировать столбец номер 5, нам надо определить лежащий в основе PropertyDescriptor для этого столбца и передать этот PropertyDescriptor методу ColumnHeaderClicked. Это можно реализовать двумя способами.

Вызовом свойства GridColumnStyle.PropertyDescriptor столбца. Однако это свойство иногда возвращает null, если наш DataGrid связан с заказной коллекцией данных через MappingName.

Если наш DataGrid связан с заказной коллекцией данных MyCollection, мы создадим TableStyle и несколько GridColumnStyles и свяжем их MappingName. MappingName из TableStyle будет тогда "MyCollection" и MappingName из ColumnStyle будет содержать имя некоторого свойства, которое показывает столбец. Итак, мы можем получить объект PropertyDescriptor, ища свойство с именем, равным MappingName столбца.
Как только у нас есть объект PropertyDescriptor, мы можем просто вызвать private-метод, используя System.Reflection.

Итак, код:

public class MyDataGrid : DataGrid
{
 // сортировка столбца по его индексу
 public void SortColumn(int columnIndex)
 {
if(this.DataSource!=null &&
((System.Collections.IList)this.DataSource).Count>0)
{
// выяснение типа выделенного объекта
Type sourceType = ((System.Collections.IList)this.DataSource)[0].GetType();
 
// получение PropertyDescriptor для отсортированного столбца,
// предполагая, что используется TableStyles[0] в datagrid...
// (измените при необходимости)
System.ComponentModel.PropertyDescriptor pd =
this.TableStyles[0].GridColumnStyles[columnIndex].PropertyDescriptor;
 
// если строчка кода выше не сработала, попытаемся получить
// propertydescriptor через MappingName
if(pd == null)
{
System.ComponentModel.PropertyDescriptorCollection pdc =
System.ComponentModel.TypeDescriptor.GetProperties(sourceType);
pd =
pdc.Find( this.TableStyles[0].GridColumnStyles[columnIndex].MappingName,
false);
}
 
// вызовем метод ColumnHeaderClicked используя system.reflection
System.Reflection.MethodInfo mi =
typeof(System.Windows.Forms.DataGrid).GetMethod("ColumnHeaderClicked",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic);
mi.Invoke(this, new object[] { pd });
}
 }
}



































Вот и все.

Автор: Terry Denham 6 Aug 2004. Перевод: MC707 30 Jan 2005



Опубликовал admin
17 Мар, Четверг 2005г.



Программирование для чайников.