I've searched for an example of sorting a DataGridView on multiple columns, but don't seem to be able to find an example which does what I would like.
Basically, I have a bound DataGridView control (bound to a DataTable/DataView), and the bound DataTable has two columns:- priority and date. I would like to sort by date within priority. That is, the priority column takes precendence, then its the date but both can be ascending or descending.
So, for example, I may have low priority, early date first (order by priority asc, date asc), and, by clicking the date column header, switch to low priority, late date first (order by priority asc, date desc). If I then click on the priority, I would like to have high priority first, then late date (the current sort order for the date column - order by priority desc, date desc), but then be able to click the date column header to switch to high priority, early date (order by priority desc, date asc).
Ideally, I would like sort glyphs on both columns to show ascending or descending.
Any ideas or pointers would be gratefully received.
This (see below) seems to get pretty close, but the glyphs aren't working right.
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
DataSet1 dataset;
public Form1()
{
InitializeComponent();
dataset = new DataSet1(); // two columns: Priority(Int32) and date (DateTime)
dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("01-jan-10"));
dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("02-jan-10"));
dataset.DataTable1.AddDataTable1Row(1, DateTime.Parse("03-jan-10"));
dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("04-jan-10"));
dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("05-jan-10"));
dataset.DataTable1.AddDataTable1Row(2, DateTime.Parse("06-jan-10"));
dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("07-jan-10"));
dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("08-jan-10"));
dataset.DataTable1.AddDataTable1Row(3, DateTime.Parse("09-jan-10"));
dataGridView1.DataSource = dataset.DataTable1.DefaultView;
dataGridView1.AllowUserToAddRows = false;
dataGridView1.Columns[0].SortMode = DataGridViewColumnSortMode.Programmatic;
dataGridView1.Columns[1].SortMode = DataGridViewColumnSortMode.Programmatic;
dataGridView1.Columns[0].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
dataGridView1.Columns[1].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
}
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
DataGridViewColumn[] column = new[] { dataGridView1.Columns[0], dataGridView1.Columns[1] };
DataGridViewColumnHeaderCell headerCell = dataGridView1.Columns[e.ColumnIndex].HeaderCell;
if (headerCell.SortGlyphDirection != SortOrder.Ascending)
headerCell.SortGlyphDirection = SortOrder.Ascending;
else
headerCell.SortGlyphDirection = SortOrder.Descending;
String sort = column[0].DataPropertyName + " " + fnSortDirection(column[0])
+ ", "
+ column[1].DataPropertyName + " " + fnSortDirection(column[1]);
dataset.DataTable1.DefaultView.Sort = sort;
this.textBox1.Text = sort;
}
private String fnSortDirection(DataGridViewColumn column)
{
return column.HeaderCell.SortGlyphDirection != SortOrder.Descending ? "asc" : "desc";
}
}
}
Sort (this. dataGridView1. Columns["day"], ListSortDirection. Ascending);
If DataGridView has a DataView as its DataSource, then setting the Sort string for that DataView causes an immediate sort of the DataView, and that sort shows right away in the bound DataGridView control. The Sort string can include multiple columns, each of which can be indicated to sort ASC or DESC.
The DataGridView control in C# provides automatic sorting, so that you can manually sort any column in the datagridview control. You can sort the data in ascending or descending order based on the contents of the specified column. Also you can see the DataGridView sorting when user clicks on the column header.
The first time I read this, I totally missed the part about sorting by multiple columns simultaneously (my fault, not yours; the question was perfectly clear).
If that's the case, you are going to have to write the code that handles this yourself. The provided DataGridView
control doesn't support multi-column sorting by default. Fortunately, others have already done a lot of the work to implement this for you. Here are a few samples:
Alternatively, if you bind your DataGridView
to a data source, that data source can be sorted on multiple columns and the DataGridView
control will respect that sorting. Any data source that implements IBindingListView
and exposes a Sort
property will work for multi-column sorting.
However, regardless of the route that you choose to enable multi-column sorting, you aren't going to have much success in coercing the DataGridView
to display the sort arrow glyph on multiple columns. The easiest solution here is to custom draw only the column headers to provide your own sort glyph.
To do this, attach a handler to the DataGridView.CellPainting
event and check for a RowIndex
of -1 (indicating a column header). There's a full sample of owner-drawn column headers here. I strongly recommend sticking with the conventional arrow icon, but once you go this route, the options are truly unlimited. You can make your column headers look like anything you want, and even indicate the relative weight of each column in the sort order using different icons.
You can also choose to derive a new class from DataGridViewColumnHeaderCell
and override its Paint
method. This is probably a cleaner, more object-oriented way of accomplishing the same thing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With