Many applications that display projections of LINQ to SQL queries in DataGridView controls require sorting on a programmatic or user-selectable column and with a specified sort direction. Some projects also need to programmatically filter the DataGridView's or other data-bound control's BindingSource component.
LINQ to SQL DataContext.DataTable objects offer a new GetNewBindingList() method that produces an IBindingList<T> object to supply a sortable BindingList.DataSource or DataGridView.DataSource property value. However IBindingList<T> doesn't support filtering; for that feature you need an IBindingListView<T> object.
Applying the IEnumerable<T>.ToList(), IQueryable<T>.ToList() or ISingleResult<T>.ToList() method returns a generic List<T> object that doesn't support sorting or filtering. All IBindingListView<T> objects support filtering and sorting; some support advanced sorting on multiple columns. Implementing the IBindingListView interface isn't a piece of cake, as demonstrated by the few working examples you'll find on the Web.
In searching for a wrapper for List<T> objects that would provide advanced (multi-column) sorting and filtering, I ran across Andrew Davey's BindingListView (blw) project on SourceForge, where it's offered under a BSD license. Andrew's an independent .NET developer in Bristol, UK and a student at the University of Warwick. He claimed in August 2006 BindingListView speedy sorting blog entry that blw sorts faster than the DataGridView.
I downloaded the C# 2.0 source code and did the following to give the BindingListView<T> class a test drive with a BindingSource component and DataGridView control populated by a List<T> object from a LINQ query:
- Added it as a project to my DynamicSQLTestHarness.sln LINQ to SQL performance analysis project.
- Created a project reference for the VB 9.0 WinForm client (see screen capture below).
- Added an Imports Equin.ApplicationFramework directive.
- Added a blvOrders = New BindingListView(Of Order)(lstOrders) statement to create a BindingListView(Of Order) object from the List(Of Order) object.
- Supplied an anonymous method to deliver the filter expression.
- Provided an SQL ORDER BY clause to sort multiple columns.
Andrew hadn't LINQ-enabled blw, so the BindingListView(Of Order)class threw exceptions when attempting to create a BindingListView(Of Order_Detail) object from each Order_Details EntitySet. A simple hack that tests for the presence of the ` character in the Equin.ApplicationFramework.BindingListView`1[DynamicSQLTestHarness.Order_Detail] typeName variable and returns null instead of the unwanted instance solved that problem.
Click image for full-size capture.
The screen capture shows the test harness after opening the form and loading the Customers, Orders, and Order_Details grids. Notice that the OrdersBindingSource reports that Advanced Sorting and Filtering is supported.