Search code examples
.netlinqobjectdatasource

How to reassign DataSource of ObjectDataSource after sorting?


I have a Gridview that has an ObjectDataSource bound and I am doing sorting on the columns. In the Sorting event I call the following:

e.Cancel = True
Me.ods.Select()
Me.gv.DataBind()

All is fine. Now in the ODS_Selected event, I manipulate the returned list collection using a LINQ OrderBy statement. The problem is the OrderBy statement does not modify the elements directly in the collection and returns the result as an IEnumerable.

Still no big deal, I thought I could just take the result of the query (which has the items in the proper order) and reassign the referenced return collection (now a new variable) and be done. It does not work (ordering does work but not datasource manipulation) and nothing happens visually - no changes.

If I use a LINQ Sort this whole procedure works perfectly, because a .Sort manipulates the items in the collection directly. However I am using Reflection to reflect on the sort expression because children of Instance properties are used and bound and that makes sorting not so straight forward. Based on help from here (How do I order a collection based on a child property using LINQ or a Lambda?) I got all the sorting working so I can't use .Sort unless it's after the call to .OrderBy.

Here is the code from the ODS_Selected event:

Dim MyData As New List(Of MyCustomClass)
'Because objects are Reference types, setting RequestQueueData = e.ReturnValue means they will share the same memory address and any modifications to 'MyData will be reflected in 'e'.
MyData = e.ReturnValue
Dim query As IEnumerable(Of MyCustomClass) = MyData.OrderBy(blah,blah)

I have tried the following and none of them have worked:

MyData = query

...and tried:

MyData = query.ToList()

..and tried:

MyData.Clear()
MyData.AddRange(query)

The last one clears the collection and the .AddRange does not load anything back in: Count = 0, even though there are 9 results in the query results.

Any ideas on how to manipulate that reference type MyData to load it up or reassign it with the results that have been ordered?

Thanks!

EDIT: Tried this as well and nothing happens to the bound Gridview's data. The collection after reassignment is perfect but nothing happens. Only when I use a .Sort on the collection for testing non-child instance properties does it work as I want. .`OrderBy' just is not permanently modifying that collection even though after reassignment it looks perfect:

Dim MyData2 As New List(Of MyCustomClass )
If query IsNot Nothing Then
 For Each mc As MyCustomClass In query.ToList()
   MyData2 .Add(req)
 Next
End If

MyData = New List(Of BLL.Entities.Request)
'After this point, MyData & MyData2 are in the proper order.
MyData  = MyData2

Solution

  • OK this does work. Reassinging a new variable and then adding it back in does the trick and accomplishes what I want to do:

    If query IsNot Nothing Then
       Dim queryTemp = query.ToList()
       MyData.RemoveRange(0, MyData.Count)
       MyData.AddRange(queryTemp)
    End If
    

    In my case, since ordering was done directly on the MyData object, I needed to place results in a new variable because once RemoveRange is called, both query and MyData will be empty. Then I add the sorted/ordered items back into the collection. Again, MyData is a reference to underlying datasource being bound.

    This stemmed from the fact that.OrderBy does NOT change the actual element order - it is just reading the items of the collection in a particular order without changing the locations of the items in the collection. .Sort will actually sort the collection – thereby changing the locations of the items in the collection. However I couldn't use .Sort because of the specialized needs returned by the .OrderBy from a custom method call to break down an instance property sort expression (i.e. ParentObject.FullName as opposed to the simple solution where the sort expression is just FullName as all the examples provide)