Sort DataGridView in C#

by Igor Katenov, Lead Developer of 10Tec Products

Microsoft's DataGridView control, supplied as a part of the .NET Framework starting with the version 2.0, is a versatile grid control for displaying and manipulating tabular data. It also provides many basic features any serious grid control must have, including sorting. For instance, you can sort a DataGridView column when you click the column's header:

Sort DataGridView column in C#

However, there are many subtleties and nuances related to DataGridView sorting. The aim of this article is to highlight main possible troubles you can face when you sort DataGridView in C#.

Sorting a DataGridView column

The MSDN documentation for the DataGridViewColumn.SortMode Property states that DataGridView sorts a column if the column's SortMode property is set to DataGridViewColumnSortMode.Automatic, which is the default setting for any DataGridViewTextBoxColumn. You might suppose then that a user can simply sort by any column by clicking on the column's heading, but surprisingly, this is not the case!

The explanation lies in the fact that DataGridView does not internally sort its rows itself. Instead, it exploits the sorting functionality of the attached data source, and if the data source does not provide sorting functionality, DataGridView column sorting is not available also. To be more precise, the data source must implement the IBindingList interface with sorting support (namely the SupportsSorting member and all related members like IsSorted, ApplySort, and so on). That should answer all your potential future questions like why DataGridView does not sort columns of a LINQ query result, items of an EntityCollection from the Entity Framework, or even a list object – because all those data sources do not support built-in sorting. It seems, the only native .NET class that has built-in sorting is DataView, which is used implicitly when you assign a DataTable or a similar ADO.NET data source to the DataSource property of a DataGridView control.

One of the possible solutions to this problem is to wrap your data into an IBindingList object that implements sorting. The Internet can supply numerous examples of creating a so called SortableBindingList class for that. Below is a link to a StackOverflow question that demonstrates how to implement a SortableBindingList for a custom class:

C# - troubles with sorting datagridview

Disable DataGridView sorting

Now we know how to enable sorting in a DataGridView, but we may need to implement the opposite task – disable DataGridView sorting. If you want to disable column sorting when the user clicks a DataGridView's column headers, simply set the aforementioned SortMode property for your DataGridView columns to DataGridViewColumnSortMode.NotSortable.

If you need to disable column sorting for all columns, you can write a universal code and avoid duplicating this setting for every individual column. Below is a typical example how to disable DataGridView sorting for all columns in C#:

private void dataGridView1_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
   dataGridView1.Columns[e.Column.Index].SortMode = DataGridViewColumnSortMode.NotSortable;
}

It implies that you attach this event handler to the DataGridView's ColumnAdded event before you define columns or the DataGridView generates them automatically when you bind the DataGridView to a data source. Other solutions can be found in this thread on StackOverflow.

How to sort DataGridView programmatically

So far, we have been discussing interactive sorting in DataGridView i.e. the sorting performed when the user clicks a DataGridView column header. In a real-world app you may need to sort DataGridView programmatically from C# code. There may be several reasons for that. For instance, your users may want to see a DataGridView sorted by a column in descending order by default when they launch your app.

DataGridView provides you with the Sort method you should use for that. We need one of its overloaded versions that accepts the DataGridView column to sort by and the desired sort order. Below is a C# example that demonstrates how to sort a DataGridView programmatically by the "Date Added" column in descending order:

dataGridView1.Sort(dataGridView1.Columns["DateAdded"],
   System.ComponentModel.ListSortDirection.Descending);

One important note though, when you retrieve a DataGridView column object using the Columns collection, don't forget that you must use the name of the column but not its column header text – they may differ from each other in the general case.

Custom sorting in DataGridView

Continuing the topic of programmatic sorting in DataGridView, let's note the SortCompare event used to implement custom sorting in DataGridView. This event is raised when you call the overloaded version of the Sort method mentioned above (by the way, it also works when we click a column's header of a DataGridView in the interface to sort it by that column). If you want to order rows using a custom rule, you code your comparison logic in a handler of the SortCompare event and set its e.Handled argument to True to tell the DataGridView that it should not do its standard comparison work.

The Microsoft Docs portal contains a wonderful C# example of Custom Sorting Using the SortCompare Event. It demonstrates how to sort the selected column and use the values of the ID column to determine the final row order if the column contains duplicate values.

Unfortunately, there is one serious limitation on the use of custom sorting in DataGridView: the SortCompare event can be used only when DataGridView works in unbound mode.

Sort DataGridView by multiple columns programmatically (unbound mode)

One of the overloaded versions of DataGridView’s Sort method allows you to sort DataGridView by multiple columns programmatically in unbound mode. You need to use the other overloaded version of the method that accepts an object implementing the System.Collections.IComparer interface. A classic example of this interface usage demonstrates how to sort unbound DataGridView by two columns:

Sort unbound DataGridView by multiple columns programmatically

The C# source code of the custom comparer used for this DataGridView is as follows:

public class DGVComparer : System.Collections.IComparer
{
  public int Compare(object x, object y)
  {
    DataGridViewRow row1 = (DataGridViewRow)x;
    DataGridViewRow row2 = (DataGridViewRow)y;

    int compareResult = string.Compare(
        (string)row1.Cells[0].Value,
        (string)row2.Cells[0].Value);

    if (compareResult == 0)
    {
      compareResult = ((int)row1.Cells[1].Value).CompareTo((int)row2.Cells[1].Value);
    }

    return compareResult;
  }
}

Below is the corresponding code snippet that demonstrates how to use this custom comparer:

dataGridView1.Sort(new DGVComparer());
dataGridView1.Columns[0].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
dataGridView1.Columns[1].HeaderCell.SortGlyphDirection = SortOrder.Ascending;

Note that we set the sort glyphs manually as our unbound DataGridView knows nothing about the current sort order of its columns.

This approach can be used to sort DataGridView when the user clicks its column headers. Generally this logic is put in an event handler of the ColumnHeaderMouseClick event. But it’s very hard to implement this technique if you want to provide your users with the ability to sort more than two columns in an unbound DataGridView, especially if the columns store values of different data types. Return to the source code of the custom comparer used above and see that we hard-coded the comparison logic for the two columns of the predefined data types.

Alternative DataGridView sorting solution – iGrid.NET

10Tec iGrid.NET is a WinForms grid control similar to DataGridView, and it can be considered as a superior DataGridView alternative in many aspects. You can find out more about all features of this control in the product section on this website, but let us highlight its sorting functionality and how this compares to DataGridView in this article dedicated to sorting in DataGridView.

First of all, multi-column sorting is built-in. The user can simply click iGrid's column headers holding down the Shift or Ctrl key to sort this unbound DataGridView replacement by multiple columns:

Multiple column sort in unbound DataGridView replacement

Notice that the column headers of the sorted columns display numbers after the sort glyphs. These numbers indicate the order of the columns in the current sort criteria.

Compared to DataGridView, you can sort multiple columns in iGrid regardless of the data source used to populate it. And if required, custom sorting is also at your disposal at any time.

Next time you are fighting with sorting DataGridView in C#, may we suggest you try iGrid.NET instead?

Read more about the 10Tec DataGridView alternative »