Need help sorting within a GridView / WebForm

Need help sorting within a GridView / WebForm

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


bedford_hopms posted on Wednesday, May 17, 2006

WinForms has the SortedBindingList.vb for sorting.  But it appears sorting is not supported at this time in WebForms.  The only thing I see that comes close is the “CanSort” method on CSLADataSourceView, which hardcoded to "False".

 

Am I missing something?  Has anybody solved this issue in a way that doesn’t require a round trip with each new sort?

 

Thanks in advance.

vivus replied on Wednesday, May 17, 2006

You would use the SortedBindingList for the web as well.  I really don't know of any way that you could currently do a total solution of declaritive programming with CSLA on the web, maybe one day.  But for now you will need to a combination of both declaritive & non declartive programming.


<csla:csladatasource id="cslaTransactionsWebView" TypeName="TransactionWebViewList" assemblyName="App_Code" runat="server">
</csla:csladatasource>


(note, don't use code in your App_Code folder/dll as i'm using a modified version of tne c# version of CSLA 2.0 )


ok set up your CLSA sorting object, similar to how it shows in the book, but instead, use a SortedBindingList


public SortedBindingList<TransactionWebView> GetTransactionWebViewList() {
            object businessObject1 =
                HttpContext.Current.Session["transactions"];
            if (businessObject1 == null ||
                !(businessObject1 is SortedBindingList<TransactionWebView>)) {
                businessObject1 = new SortedBindingList<TransactionWebView>(
                    TransactionWebViewList.GetTransactionWebViewList(this.User.ContactID, false));
                UpdateTransactionWebViewList((SortedBindingList<TransactionWebView>)businessObject1);
            }
            return (SortedBindingList<TransactionWebView>)businessObject1;
        }

    public void UpdateTransactionWebViewList(SortedBindingList<TransactionWebView> obj) {
            HttpContext.Current.Session["transactions"] = obj;
        }


now here is something that isn't really documented, but after the grid sorts when using a declaritive datasource, it executes the select method from the declaritive datasource
so don't forget the following. ....

void cslaTaskCategoryWebView_SelectObject(object sender, SelectObjectArgs e) {
        e.BusinessObject = GetTaskCategoryWebViewList();
    }



now for overriding the sorting method of the grid.

void gdvTransactions_Sorting(object sender, GridViewSortEventArgs e) {
        ListSortDirection direction = ListSortDirection.Descending;
        if (e.SortDirection == SortDirection.Ascending)
            direction = ListSortDirection.Ascending;

        SortedBindingList<TransactionWebView> obj1 = GetTransactionWebViewList();
        obj1.ApplySort(e.SortExpression, direction);
        UpdateTransactionWebViewList(obj1);
    }

now it should sort....

however i have been having issues with the gridview sorting while using a declaritive datasource and having the sorting and paging using callbacks....but this could also be because i'm doing alot of testing with csla and atlas and yadda yadda yadda. so atlas could be throwing it off, the sorting event doesn't fire on callback, but the paging works fine.  however the sorting event will fire on postback. 

david.wendelken replied on Thursday, July 27, 2006

vivus:

public SortedBindingList<TransactionWebView> GetTransactionWebViewList() {
            object businessObject1 =
                HttpContext.Current.Session["transactions"];
            if (businessObject1 == null ||
                !(businessObject1 is SortedBindingList<TransactionWebView>)) {
                businessObject1 = new SortedBindingList<TransactionWebView>(
                    TransactionWebViewList.GetTransactionWebViewList(this.User.ContactID, false));
                UpdateTransactionWebViewList((SortedBindingList<TransactionWebView>)businessObject1);
            }
            return (SortedBindingList<TransactionWebView>)businessObject1;
        }

    public void UpdateTransactionWebViewList(SortedBindingList<TransactionWebView> obj) {
            HttpContext.Current.Session["transactions"] = obj;
        }

Had a dickens of a time to get this to compile.  Finally realized there are two BO library objects being used, not one.  TransactionWebView and TransactionWebViewList, representing the item object and the collection object respectively.

Thought I would point it out for others like me who are suffering from a "slow brain day". :)

vivus:

... now for overriding the sorting method of the grid...

ListDirection requires a "using System.ComponentModel;" directive.

After that, it worked like a charm!

Thanks!

glenntoy replied on Wednesday, May 17, 2006

I don't know if this will be the approriate solution or its efficient. In my case I use ReadOnlyList but surely it will worked with BusinessBaseList. First, I wrapped my ReadOnlyList with SortedBindingList. Please see code below.

Public Class SortedYourReadOnlyList
    Inherits SortedBindingList(Of YourReadOnlyBase)

    Private Sub New(ByVal l As YourReadOnlyList)
        MyBase.New(l)
    End Sub

    Public Shared Function NewSortedYourReadOnlyList(ByVal l As ReadOnlyList) As SortedYourReadOnlyList
        Return New SortedTimesheetList(l)

    End Function

End Class

As you can noticed, it wont worked in ASP.NET 2.0 when you clicked the sorted columns compared to winforms. So I decided to trigger the sorting programatically. I used the GridView_Sorting() event to get the column to be sorted and what direction. I store the Gridview sorting event handler in a session then. Please see code below:

Protected Sub GridView1_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles grdTimesheet.Sorting
   Session("willSort") = e
End Sub


Protected Sub XXX_SelectObject(ByVal sender As Object, ByVal e As Csla.Web.SelectObjectArgs) Handles XXX.SelectObject

   If Session("YourSortedReadOnlyList") Is Nothing Then
     Session("YourSortedReadOnlyList") = YourSortedReadOnlyList.NewYourSortedReadOnyList( _
      YourReadOnlyList.GetList(New Criteria(Your Criteria)))
   End If


   If Session("willSort") IsNot Nothing Then

        Dim _sort As GridViewSortEventArgs = Session("willSort")
       
        Dim _slist As YourSortedReadOnlyList = CType(Session("YourSortedReadOnlyList"), YourSortedReadOnlyList)
            _slist.ApplySort(_sort.SortExpression, _sort.SortDirection)
            Session("YourSortedReadOnlyList") = _slist
            Session("willSort") = Nothing
 
   EndIf

   e.BusinessObject = Session("YourSortedReadOnlyList")

glenntoy replied on Wednesday, May 17, 2006

Virus, its so funny your posting in C# and I'm posting in VB.NET. At least the other readers could have an option then. But more or less, I think we do have same solution. V

Cheers,

Glenn

fabiousa7 replied on Friday, December 01, 2006

I am having this same problem for a while now, but i was wondering if anyone was able to figure out the actual reason of this problem, and maybe something that is more like a fix than a work-around?

thanks,

Fabio

boo replied on Sunday, March 25, 2007

This is just the design of CSLA, but I found a pretty clean way to implement in code behind rather than carrying things around in session - just do the sort when selecting:

protected void CslaDataSource1_SelectObject(object sender, Csla.Web.SelectObjectArgs e)

{

SortedYourList list = SortedYourList.NewSortedYourList(YourList.FactoryMethod());

if (GridView1.SortExpression != string.Empty)

{

switch (GridView1.SortDirection)

{

case SortDirection.Ascending:

list.ApplySort(GridView1.SortExpression, ListSortDirection.Ascending);

break;

case SortDirection.Descending:

list.ApplySort(GridView1.SortExpression, ListSortDirection.Descending);

break;

}

}

e.BusinessObject = list;

}

miloy001 replied on Sunday, July 29, 2007

BOO:

My EditableObject list does not have ApplySort() but you have list.ApplySort(). Do you added your own ApplySort or something else?

dantruj replied on Monday, July 30, 2007

I am having a problem with the gridview and filteredbindinglist in how best to databind the filtered list.

The cslaDataSource_SelectObject fires when a user wishes to sort a column, the list is obtained, sorted then set back to the grid like e.businessobject = sortedList.  That works great, but how can I do this for a filteredBindingList?  I want to be able to let the user entered a filtered value into a text box and have the filter begin by pressing a button on the web form.  The button event fires, the list is filtered but I do not know how to set the datagrids binding to show this filtered list.

MTmace replied on Tuesday, April 07, 2009

I know this is a really old post but perhaps I have something to add.

Sorting should happen in the UI, not the business object. So if you are using .net 2.0, CSLA 2.0 you should be using the sortedBindingList as described on page 247 (C# 2005).
Get the normal collection then create a sortedBindingList, then execute the "ApplySort" method.
Then bind the sorted list to the grid.

NormalCollection nc = getCollection();

Csla.
SortedBindingList<NormalCollection > sortedList = new Csla.SortedBindingList<NormalCollection >(nc);
sortedList.ApplySort(
"Property", System.ComponentModel.ListSortDirection.Descending);

this.gv.DataSource = sortedList;
this.gv.DataBind();

In .net 3.5 LINQ should be used.

sgraham replied on Tuesday, June 30, 2009

Here's what I found after almost a day of searching.  I feel this is quick and easy and reusable!

 

Using statements needed:

using System.Collections.Generic;

using System.Linq.Expressions;

 

Create a static class:

public static class MyExtensions

{

   public static IEnumerable<T> Sort<T>(IEnumerable<T> source, string sortExpression, SortDirection sortDirection)

   {

   var _param = Expression.Parameter(typeof(T), "item");

   var _sortExpression = Expression.Lambda<Func<T, object>>

   (Expression.Convert(Expression.Property(_param, sortExpression), typeof(object)), _param);

   if (sortDirection == SortDirection.Descending)

      return source.AsQueryable<T>().OrderByDescending<T, object>(_sortExpression);

   else

   return source.AsQueryable<T>().OrderBy<T, object>(_sortExpression);

   }

}

 

Call it using the following:

IEnumerable<PromotionPlanning.Utilities.Classes.EventInfo> eventList;

protected void EventListDataSource_SelectObject(object sender, Csla.Web.SelectObjectArgs e)

{

   eventList =

      from f in GetProdEventList()

      select f;

   if (gvEventList.SortExpression.Length > 0)

   {

      eventList = MyExtensions.Sort<EventInfo>(eventList, gvEventList.SortExpression, gvEventList.SortDirection);

   }

   e.BusinessObject = eventList;

}

 

Enjoy!

Copyright (c) Marimer LLC