How to enable sorting of a DataGridView when a user clicks on a column heading?

I have a datagridview in my form and I populate it with this:

dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth }) .OrderBy(s => s.Apellidos) .ToList(); 

Now I use s.Apellidos as the default sort, but I would also like to allow users to sort by clicking on the column heading.

This type will not modify the data in any way, it is just a bonus on the client side to facilitate the search for information when scanning the screen with your eyes.

Thanks for the suggestions.

+54
sorting c # winforms datagridview
Apr 05 2018-11-11T00:
source share
13 answers

Set the entire column (which can be sorted by user) SortMode property for Automatic

 dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth }) .OrderBy(s => s.Apellidos) .ToList(); foreach(DataGridViewColumn column in dataGridView1.Columns) { column.SortMode = DataGridViewColumnSortMode.Automatic; } 

Edit: Since your datagridview is associated with a linq request, it will not be sorted. Therefore, please follow the link that explains how to create a sortable binding list and then pass it as a data source to a datagridview.

+38
Apr 05 2018-11-11T00:
source share

As Niraj suggested, use a SortableBindingList . I have used this very successfully with a DataGridView.

Here's a link to the updated code I used - View SortableBindingList - Take Two

Just add two source files to your project and you will be in business.

Source is in SortableBindingList.zip

+23
Apr 05 '11 at 18:15
source share

Your data grid should be tied to the sorted list first.

Create this event handler:

  void MakeColumnsSortable_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e) { //Add this as an event on DataBindingComplete DataGridView dataGridView = sender as DataGridView; if (dataGridView == null) { var ex = new InvalidOperationException("This event is for a DataGridView type senders only."); ex.Data.Add("Sender type", sender.GetType().Name); throw ex; } foreach (DataGridViewColumn column in dataGridView.Columns) column.SortMode = DataGridViewColumnSortMode.Automatic; } 

And initialize the event of each of your datragrids as follows:

  dataGridView1.DataBindingComplete += MakeColumnsSortable_DataBindingComplete; 
+6
Aug 25 2018-11-11T00:
source share

You can use the DataGridViewColoumnHeaderMouseClick event as follows:

 Private string order = String.Empty; private void dgvDepartment_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { if (order == "d") { order = "a"; dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth }) .OrderBy(s => s.Apellidos).ToList(); } else { order = "d"; dataGridView1.DataSource = students.Select(s => new { ID = s.StudentId, RUDE = s.RUDE, Nombre = s.Name, Apellidos = s.LastNameFather + " " + s.LastNameMother, Nacido = s.DateOfBirth }.OrderByDescending(s => s.Apellidos) .ToList() } } 
+5
Jul 21 '11 at 10:29
source share

KISS: Keep it simple, stupid

Method A: Add your own SortableBindingList class if you want to use DataBinding and sorting .

Path B: Use the sort operation List <string> , but does not work with DataBinding .

+2
Jul 15 '12 at 8:17
source share
  • Create a class that contains all the properties you need and fill them in the constructor

     class Student { int _StudentId; public int StudentId {get;} string _Name; public string Name {get;} ... public Student(int studentId, string name ...) { _StudentId = studentId; _Name = name; ... } } 
  • Create an IComparer <Student> class to be able to sort

     class StudentSorter : IComparer<Student> { public enum SField {StudentId, Name ... } SField _sField; SortOrder _sortOrder; public StudentSorder(SField field, SortOrder order) { _sField = field; _sortOrder = order;} public int Compare(Student x, Student y) { if (_SortOrder == SortOrder.Descending) { Student tmp = x; x = y; y = tmp; } if (x == null || y == null) return 0; int result = 0; switch (_sField) { case SField.StudentId: result = x.StudentId.CompareTo(y.StudentId); break; case SField.Name: result = x.Name.CompareTo(y.Name); break; ... } return result; } } 
  • In a form containing a datagrid add

     ListDictionary sortOrderLD = new ListDictionary(); //if less than 10 columns private SortOrder SetOrderDirection(string column) { if (sortOrderLD.Contains(column)) { sortOrderLD[column] = (SortOrder)sortOrderLD[column] == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending; } else { sortOrderLD.Add(column, SortOrder.Ascending); } return (SortOrder)sortOrderLD[column]; } 
  • In the datagridview_ColumnHeaderMouseClick event handler, do something like this

     private void dgv_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { StudentSorter sorter = null; string column = dGV.Columns[e.ColumnIndex].DataPropertyName; //Use column name if you set it if (column == "StudentId") { sorter = new StudentSorter(StudentSorter.SField.StudentId, SetOrderDirection(column)); } else if (column == "Name") { sorter = new StudentSorter(StudentSorter.SField.Name, SetOrderDirection(column)); } ... List<Student> lstFD = datagridview.DataSource as List<Student>; lstFD.Sort(sorter); datagridview.DataSource = lstFD; datagridview.Refresh(); } 

Hope this helps

+1
Apr 05 '11 at 16:40
source share

If you get an error, for example

An unhandled exception of type 'System.NullReferenceException' occurred in System.Windows.Forms.dll

if you are working with a SortableBindingList, your code probably uses some loops on the rows of the DataGridView and also tries to access the empty last row! (BindingSource = null)

If you do not need to allow the user to add new rows directly to the DataGridView, this line of code easily solves the problem:

 InitializeComponent(); m_dataGridView.AllowUserToAddRows = false; // after components initialized ... 
+1
Jun 17 '13 at 13:07 on
source share

Another way to do this is to use the System.Linq.Dynamic library. You can get this library from Nuget. No need for any custom implementations :).

 using System.Linq.Dynamic; private bool sortAscending = false; private void dataGridView_ColumnHeaderMouseClick ( object sender, DataGridViewCellMouseEventArgs e ) { if ( sortAscending ) dataGridView.DataSource = list.OrderBy ( dataGridView.Columns [ e.ColumnIndex ].DataPropertyName ).ToList ( ); else dataGridView.DataSource = list.OrderBy ( dataGridView.Columns [ e.ColumnIndex ].DataPropertyName ).Reverse ( ).ToList ( ); sortAscending = !sortAscending; } 
+1
Apr 19 '17 at 1:10
source share

Just in case someone is still looking for him, I did this on VS 2008 C #.

In the EventHeaderMouseClick column add data binding for gridview and submit the order by field as a parameter. You can get the field with a click:

 dgView.Columns[e.ColumnIndex].Name 

In my case, the header names are similar to the view field names.

0
Jul 02 '13 at 15:52
source share

I have a BindingList <> object binding as a data source for a dataGridView.

 BindingList x1; x1 = new BindingList<sourceObject>(); BindingSource bsx1 = new BindingSource(); bsx1.DataSource = x1; dataGridView1.DataSource = bsx1; 

When I clicked the column heading, sorting does not happen. I used the SortableBindingList answer provided by Tom Bushell. By including two source files in your project

  • SortableBindingList.cs
  • PropertyComparer.cs

Then this change is made to my code:

 Be.Timvw.Framework.ComponentModel.SortableBindingList x1; // 1 x1 = new Be.Timvw.Framework.ComponentModel.SortableBindingList<sourceObject>(); // 2 BindingSource bsx1 = new BindingSource(); bsx1.DataSource = x1; dataGridView1.DataSource = bsx1; 

After these changes, I built my program. Now I can sort by clicking on the column headers. Only two lines need to be changed; they stand out in the code snippet above, leaving comments.

0
Jun 18 '14 at 16:36
source share


There is a fairly simple solution when using the Entity Framework (version 6 in this case). I'm not sure, but it seems that the ObservableCollectionExtensions.ToBindingList<T> method returns an implementation of the sort binding list . I did not find the source code to confirm this assumption, but the object returning from this method works very well with the DataGridView , especially when sorting columns by clicking on its headers.

The code is very simple and relies only on .net and entity framework classes:

 using System.Data.Entity; IEnumerable<Item> items = MethodCreatingItems(); var observableItems = new System.Collections.ObjectModel.ObservableCollection<Item>(items); System.ComponentModel.BindingList<Item> source = observableItems.ToBindingList(); MyDataGridView.DataSource = source; 
0
Nov 03 '16 at 10:29
source share

I suggest using DataTable.DefaultView as a data source. Then the line below.

 foreach (DataGridViewColumn column in gridview.Columns) { column.SortMode = DataGridViewColumnSortMode.Automatic; } 

After that, the gridview itself will manage the sorting (upward or downward supported).

0
May 16 '17 at 9:07 a.m.
source share

You do not need to create a binding data source. If you want to apply sorting to all your columns, then this is a more general solution,

 private int _previousIndex; private bool _sortDirection; private void gridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) { if (e.ColumnIndex == _previousIndex) _sortDirection ^= true; // toggle direction gridView.DataSource = SortData( (List<MainGridViewModel>)gridReview.DataSource, gridReview.Columns[e.ColumnIndex].Name, _sortDirection); _previousIndex = e.ColumnIndex; } public List<MainGridViewModel> SortData(List<MainGridViewModel> list, string column, bool ascending) { return ascending ? list.OrderBy(_ => _.GetType().GetProperty(column).GetValue(_)).ToList() : list.OrderByDescending(_ => _.GetType().GetProperty(column).GetValue(_)).ToList(); } 

Make sure you subscribe your data grid to the ColumnHeaderMouseClick event. When a user clicks on a column, it is sorted in descending order. If you click the same column heading again, the sorting will be applied in ascending order.

0
Aug 26 '17 at
source share



All Articles