Trying to replace SortedBindingList with LINQ

Trying to replace SortedBindingList with LINQ

Old forum URL: forums.lhotka.net/forums/t/6417.aspx


Blarm posted on Friday, February 13, 2009

As per page 74 of the 2008 book I am trying to replace the obsolete SortedBindingList with LINQ.

However I commonly use a SortedBindingList of ReadOnlyList (ROL) so that I can bind to a WIndows DataGridView and have sorting on column headers become automatic.

When using LINQ on a ROL it returns a IEnumerable which is not sortable and so the user can no longer use the grid headings to sort the column.

Is there a way to get LINQ to use the LINQ to CSLA tto get a LinqBindingList which I presume will give me sorting on the grid by default.

Bill

JoeFallon1 replied on Friday, February 13, 2009

Yes. There is a way. I have been working on this for a while now.

As you noted ReadOnlyLists return IEnumerable(Of T). EditableLists return LinqBindingList(Of T).

The key is that you want to be able to pass in a String column name and Sort Direction.

In order to accomplish this you need to:

#1. Download the Microsoft Dynamic Query Library and add it to your project. This will handle String values and turn them into LINQ Expressions for you.

#2. Add this method to the MS code:

'JF - 1/5/09 added this extension:
'http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2666544&SiteID=1#2670101

<Extension()> _
Public Function ToList(ByVal query As IQueryable) As IList
Return DirectCast(Activator.CreateInstance(GetType(List(Of )).MakeGenericType(query.ElementType), query), IList)
End Function

#3. Use code like this for ReadOnlyLists:

Page level variable:
Private mSortedList As System.Linq.IQueryable

In a method like doDataBind which gets called from various places like:
   PageLoad, dg_SortCommand, dg_PageIndexChanged

Dim sortDir As String =  ListSortDirection.Ascending  '(Or Descending)
mSortedList = mROList.AsQueryable.OrderBy(strGridSortExpression &
" " & sortDir )
dg.DataSource = mSortedList.ToList

In other methods you can refer to items in the sorted list like this:

Private Sub dg_ItemDataBound(ByVal sender As System.Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dg.ItemDataBound

If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
  Dim mIndex As Integer = e.Item.DataSetIndex
  Dim item As mROList.Info = CType(mSortedList(mIndex), ROList.Info )
End If
End Sub

==============================================================

Alternatively you could strongly type things and use code like this:

'One issue you have to resolve though is:
'AllowCustomPaging must be true and VirtualItemCount must be set for a DataGrid with ID 'dg'
'when AllowPaging is set to true and the selected data source does not implement ICollection.

Private mSortedList As System.Linq.IQueryable(Of ROList.Info)

Dim sortDir As String =  ListSortDirection.Ascending  '(Or Descending)
mSortedList = mROList.AsQueryable.OrderBy(strGridSortExpression & " " & sortDir )
dg.DataSource = mSortedList  ' Note: no need for .ToList anymore

Private Sub dg_ItemDataBound(ByVal sender As System.Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dg.ItemDataBound

If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
  Dim mIndex As Integer = e.Item.DataSetIndex
  Dim item As mROList.Info = mSortedList(mIndex) ' Note: no need to cast anymore.
End If
End Sub

==============================================================

I think sorting and filtering for ReadOnly lists works with the MS Dynamic Query Library.

I am working with Rocky and Aaron to get it to work for Editable Lists. Right now a normal LINQ query works for multi-column sorting as long as there is no Where clause.

Single column sorting and filtering of normal LINQ queries works for Where and OrderBy.

MS Dynamic query works for single column sorting only. No filtering yet. We are still resolving the differences in implementation of Expressions that get passed from LINQ and MS Dyn. Query.

Joe

 

Blarm replied on Monday, February 16, 2009

Thanks Joe.

It would be nice if a ROL returned a LinqBindingList so that the DatGridView sort worked automatically.

Instead I have also had to wire up the grids ColumnHeaderMouseClick event to display the correct sort glyph.

Bill

JoeFallon1 replied on Monday, February 16, 2009

Blarm:

It would be nice if a ROL returned a LinqBindingList so that the DatGridView sort worked automatically.

Bill

 

Bill,

I suggested the same thing to Rocky and got shot down. I just wanted it for the sake of consistency throughout my code: when you write a Linq query you get back a LinqBindingList. But now I have to keep track if it is a ROC or ECC.

BTW - how would a LinqBindingList resolve this issue for you? The column header is still a String value which varies at run time - so how can you write a real LINQ query at design time? You still need the MS Dynamic Query Library unless I am missing something. If so, please let me know.

Joe

 

 

Copyright (c) Marimer LLC