Presenting the SortableBindingList<T>

If you are databinding your custom objects (in a Bindinglist of <T>) to a DataGridView you will notice that the users can’t sort the rows by clicking on the columnheaders… Unlike an unbound DataGridView, the SortCompare event is not raised. Here is a class that uses IComparer to implement a BindingList that supports Sorting:

Please read the follow up article to find the updated source code.

Using this SortableBindingList is as easy as:

[code lang=”csharp”]public Form1()

SortableBindingList persons = new SortableBindingList();
persons.Add(new Person(1, “timvw”, new DateTime(1980, 04, 30)));
persons.Add(new Person(2, “John Doe”, DateTime.Now));

this.dataGridView1.AutoGenerateColumns = false;
this.ColumnId.DataPropertyName = “Id”;
this.ColumnName.DataPropertyName = “Name”;
this.ColumnBirthday.DataPropertyName = “Birthday”;
this.dataGridView1.DataSource = persons;

the sortablebindinglist at work

Feel free to download the source and demoproject:

Edit: You can find the latest implementation at BeTimvwFramework, a project where i will keep classes that i find interesting.

47 thoughts on “Presenting the SortableBindingList<T>

  1. The code got mangled and doesn’t compile as is. Can you fix this (or post the .zip)? Looks like a very good start of what I need.

  2. Apparently there was a } too much in the delegate… Anyway, as promised, i’ve added a link to the source (and a demo project).

  3. Your example works, but since I already have my own collection, I added another constructor:

    [code lang=”csharp”]public SortableBindingList(IList list)
    : base(list)

    This compiles but when I click on column header it blows up in the delegete on this line:

    [code lang=”csharp”]List itemsList = this.Items as List;[/code]

    because it could not cast and itemsList was null.

    So I changed this line to:

    [code lang=”csharp”]List itemsList = new List(Items);[/code]

    This compiles, I click on column, sort triangle appears, but it does not sort!

    I can’t figure out why…

  4. Well, i don’t know why, but these days my implementation does have a constructor that accepts an existing collection… I’ve uploaded an updated version of the source with an example of the added constructor:

    [code lang=”csharp”]
    public SortableBindingList(IEnumerable<T> enumerable)
    : base(new List<T>(enumerable))

  5. That did it! I guess it was

    foreach (T t in enumerable)
    which I was missing before in my constructor. One way or another it works

    Very handy class, thanks

  6. Pingback: Tim Van Wassenhove » Presenting the TypedList<T>

  7. I have used the above example in my own project with the effect that by DataGridView’s columns now sort, but the column order is no longer as specified in the form designer.

    For some reason, populating the SortableBindingList is reordering the DataGridView’s columns so they are in alphabetical order

  8. I solved my problem, I was binding the SortableBindingList directly to the DataGridView instead of setting up a BindingSource in-between.

  9. How would I implement a multi-column (sub) sort. It looks like ApplySortCore(…) only return the PropertyDescriptor of the column that was clicked.


  10. Hi Tim

    I have already tried your code, it works very good, but one isuue you might not probably noticed, if I have on column with all same data, when I click this column to sort, what I expect should change nothing, but each time datagridview change the order of records. any suggestion?


  11. @Malcolm:

    This is because the implementation always raises a ListChanged event… You could probably add a little tweak that does not do that…

  12. Tim,

    Great class. It is a beautiful, elegant solution to allow sorting of objects in a DataGridView.


  13. Hi Tim

    This is interesting, I look up msdn, here is some comment:”This method uses Array..::.Sort, which uses the QuickSort algorithm. This implementation performs an unstable sort; that is, if two elements are equal, their order might not be preserved. In contrast, a stable sort preserves the order of elements that are equal.”

    that means our Sort() has changed the order of binding list, even I don’t raise ListChanged event this time, but later on, when datagridview needs refresh, all records’ order will be changed. I have not found the solution so far. 🙂

  14. Hi!

    Your base class already implements the required constructors, just add

    public SortableBindingList() : base() { }

    public SortableBindingList(List list) : base(list) { }

    to initialize with an existing List.

  15. greate class!

    It would be interesting to know why so simple functionality isn’t implemented in standart NET framework by default (e.g. in BindingSource class)?
    Is it in-depth intention?

  16. Hi,,

    Is there any we can make this as a stable sort rather than a unstable sort…??

  17. You Rock man!
    We use a binding source on all our db objects and this code will make it easy to implement sorting in all our apps.

  18. Pingback: Tim Van Wassenhove » Archive » Presenting the SortableBindingList « Devmanic – Software Development Mania

  19. I would suggest also the following method, in order that newly added items are automatically sorted:
    protected override void InsertItem(int index, T item)
    if (comparer != null && index == Count)
    List itemsList = (List)this.Items;

    index = itemsList.BinarySearch(item, comparer);
    if (index < 0)
    index = ~index;
    base.InsertItem(index, item);

  20. Thanks Tim,

    Best of luck for all your future articles and all things. Thanks once again.


  21. Thank you Tim
    Been looking for this a lot until i stumbled onto your article. Great job

  22. 😀 Works beautifully, THANKS! (After hours of battling with other attempts)


  23. public static class SortableDataSourceExtension
    public static IList ToSortable(this IList list)
    return new SortableBindingList(list);

  24. But with less than T greater than T where needed to make it generic. your phorum ate my generics!

  25. How would you modify this to allow a comparer for images (ie. red/green/yellow circles that you would like grouped after a list of test in the gridview are run)?

  26. Awesome for the most part, although I’m running into an issue. When a user clicks a column in which the data is bound to a child table’s column I get a null reference exception. “Object Reference Not Set To An Instance Of An Object.” (Using Linq) And when I go back and try to save the employee it will throw the same error. It’s something to do with not being able to handle the child table.

  27. Awesome for the most part, although I’m running into an issue. When a user clicks a column in which the data is bound to a child table’s column I get a null reference exception. “Object Reference Not Set To An Instance Of An Object.” (Using Linq) It’s something to do with not being able to handle the child table.

  28. Hi Tim,
    Thank you so much. This works great for me. Do I need to add a copyright reference or give you credit beyond a comment in the header?

    Thanks again

Comments are closed.