Вот пример, который работает как электронные таблицы Google: щелчок по заголовку каждого столбца сортирует по этому столбцу и повторный щелчок по столбцу меняет направление поиска. Кроме того, он ищет в обратном порядке историю того, как вы щелкнули по столбцам, т. Е. Если вы щелкнете по столбцу D, затем B, затем C, затем A, при последнем щелчке он будет сортироваться по столбцам A, C, B, D и в направлении для каждого, что он искал, когда вы последний раз щелкнули по этому столбцу.
Он опирается на эти функции, встроенные в DataGridView:
- Если DataGridView имеет DataView в качестве своего DataSource, тогда установка строки сортировки для этого DataView вызывает немедленную сортировку DataView, и эта сортировка сразу отображается в связанном элементе управления DataGridView
- Строка сортировки может содержать несколько столбцов, каждый из которых может быть указан для сортировки ASC или DESC
- Когда вы устанавливаете строку сортировки в DataView (тем самым вызывая его сортировку), DataGridView, к которому он привязан, автоматически добавит соответствующий глиф вверх-вниз на основе первого элемента (имя и направление) в вашем виде. строка
Начнем с сортировщика:
internal class Sorter
{
internal readonly string ColumnName;
internal bool IsAscending;
internal Sorter(string columnName, bool isAscending)
{
this.ColumnName = columnName;
this.IsAscending = isAscending;
}
public override bool Equals(object other)
{ // For equivalence, compare column name only (not object ref or sort order)
if (other == null) { return false; }
if (other.GetType() != typeof(Sorter)) { return false; }
return this.ColumnName == ((Sorter)other).ColumnName;
}
public override int GetHashCode()
{ // required if we have overridden Equals
return this.ColumnName.GetHashCode();
}
public override string ToString()
{
return this.ColumnName + (this.IsAscending ? " ASC" : " DESC");
}
}
А затем соберите наши объекты Сортировщика в класс Сортировщиков:
using System.Collections.Generic;
using System.Linq;
internal class Sorters : List<Sorter>
{
internal void BringColumnToFrontOfSortingOrder(Sorter sorter)
{
if (this.Contains<Sorter>(sorter))
{
this.Remove(sorter); // remove it from where it is
}
// put it at the start
this.Insert(0, sorter);
}
// Returns a DataView sorting string like "ColName1 ASC, ColName2 DESC" etc
public override string ToString()
{
var s = new System.Text.StringBuilder();
foreach (Sorter sorter in this)
{
if (s.Length > 0) { s.Append(", "); }
s.Append(sorter.ToString());
}
return s.ToString();
}
}
И я создаю свой собственный класс MultiSortingDataGridView, производный от DataGridView, с переопределенным методом Sort, который отслеживает, по каким столбцам вы щелкнули, и вызывает своего рода DataView, который является связанным DataSource моей сетки на основе истории. кликов сортировки вашего столбца:
using System.Data;
using System.Windows.Forms;
using System.ComponentModel;
public class MultiSortingDataGridView : DataGridView // derive from DataGridView and extend it
{
private Sorters _sorters = new Sorters(); // keeping track of what column(s) we have searched by
// override the regular search with our super duper multi-column search
public override void Sort(DataGridViewColumn dataGridViewColumn, ListSortDirection direction)
{
Sorter sorter = new Sorter(dataGridViewColumn.Name, direction == ListSortDirection.Ascending);
this._sorters.BringColumnToFrontOfSortingOrder(sorter);
// Get the data view that is our data source
DataView vw = (DataView)this.DataSource;
// When you set the Sort property, it causes it to sort, and happily it sets
// the up/down glyph of the column that corresponds to your first sort-by item.
vw.Sort = this._sorters.ToString();
}
}
Затем в своей форме я проверяю, что я использую элемент управления MultiSortingDataGridView (как указано выше) вместо обычного DataGridView, и я устанавливаю его источник данных следующим образом:
DataTable tbl = SomeMethodForGettingMyTabularData(); // instantiate a data table with the data you want to show
DataView vw = new DataView(tbl); // make a data view from it
this.dgv.DataSource = vw; // bind the view as data source to my MultiSortingDataGridView control