Question Problem sorting DataGridView

paulw

Member
Joined
Dec 21, 2014
Messages
6
Programming Experience
10+
Hello All,

The problem I'm having is when I programmatically sort my DataGridView I get the following exception:

System.InvalidOperationException: DataGridView control must be bound to an IBindingList object to be sorted.

This shouldn't be happening. The data source is a DataView which of course implements IBindingList which is clear in the following pic.

datagrid_sort.PNG

As you can see, the data source implements IBindingList and the SupportsSorting property is true. My problem may be the result of upgrading to Visual Studio 2013 because the code had been working for some time. Has anybody run across this before?

if (be.SortColumn.Length > 0 && DataGrid.Columns.Contains(be.SortColumn))
{
try
{
DataGrid.Sort(DataGrid.Columns[be.SortColumn], ListSortDirection.Ascending);
}
catch (Exception ex)
{
Debug.WriteLine("Column.Sort: " + be.SortColumn);
Debug.WriteLine("Error: " + ex.ToString());
}
}

-Paul

 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,224
Location
Sydney, Australia
Programming Experience
10+
I'm curious as to why you're using programmatic sorting in the first place, given that you don't appear to be doing anything that could not be accomplished using automatic sorting.
 

paulw

Member
Joined
Dec 21, 2014
Messages
6
Programming Experience
10+
This does not sort the column:

DataGrid.Columns[be.SortColumn].SortMode = DataGridViewColumnSortMode.Automatic;

Is there something I'm missing?

 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,224
Location
Sydney, Australia
Programming Experience
10+
Sorting is automatic by default. If you simply add the columns, explicitly in the designer or implicitly by setting the DataSource, then clicking a column header will automatically sort that column. If you have bound a DataView directly or indirectly via a DataTable, clicking a column header is equivalent to assigning the corresponding column name to the Sort property of the DataView.
 

paulw

Member
Joined
Dec 21, 2014
Messages
6
Programming Experience
10+
I see. Clicking the column header does sort the column. But I would like this column to be sorted when first displayed. This used to work but it seems as if there's a .net bug now.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
3,224
Location
Sydney, Australia
Programming Experience
10+
I would like this column to be sorted when first displayed.
I just did this and it worked just like that:
private void Form1_Load(object sender, EventArgs e)
{
    var table = new DataTable();

    table.Columns.Add("Id", typeof(int));
    table.Columns.Add("Name", typeof(string));

    table.Rows.Add(1, "Peter");
    table.Rows.Add(2, "Paul");
    table.Rows.Add(3, "Mary");

    dataGridView1.DataSource = table.DefaultView;
    dataGridView1.Sort(dataGridView1.Columns[1], ListSortDirection.Ascending);
}

I added a DataGridView to the form and did nothing at all to it. Without the last line, the data was displayed in the order it was added to the table. With that last line, the data was displayed sorted by Name with a sort glyph in the header of that column. I could then click column headers to sort by either column.

By the way, there's actually no point bind the DefaultView of a DataTable because, when you bind the DataTable itself, the data actually comes from the DefaultView anyway. Only bind a DataView if you're creating multiple views of the same DataTable. Also, I recommend binding via a BindingSource. Sometimes it makes no difference but often it does and I like to be consistent. For instance, if you want to edit and save the bound data, calling EndEdit on the BindingSource will ensure any pending change is committed to the DataTable before saving.
 

paulw

Member
Joined
Dec 21, 2014
Messages
6
Programming Experience
10+
Thank you, JohnH, that worked. I had tried sorting on the DataSourceChanged event and that did not work. I didn't think to look for a different event.
 
Top Bottom