GridView Sorting Trick when using Object Datasource with custom objects


When you are using Object DataSource in ASP.Net for GridView, if your select method is returning an object that is of type DataView, DataTable or DataSet, you will be able to get sorting automatically.
But if you are like me and your architecture has a distinct DTO (Entity) layer, and you pass back and forth custom objects or generic list of these custom objects, then you are in less luck with GridView. If you
are binding GridView with Object Datasource that returns a List, you will need to implement your own custom code to do sorting.

If you google this issue, you will find different implementation that will point you to add a OnSorting event handler and more than one way to implement a custom sorting.

What my thinking is, since DataTable and DataView provides us the automatic sorting that we need, then why don’t we create
a DataTable from the List we have. We can do this elegantly using generics and reflection. Once we create a DataTable, simply pass back a DataView based on this table as return parameter from your Select Method of Object Datasource.

Here is the code for converting a List to a DataTable, (CustomObject is my custom object defined in my DTO layer)

using System;
using System.Data;
using System.Collections.Generic;
using System.Reflection;
public class Utilities
{

	public static DataTable ToDataTable(List lst) where T : CustomObject
        {
            PropertyInfo[] propertyInfos;

            System.Data.DataTable table = new DataTable("GridViewTable");
            DataColumn column=null;
            DataRow row=null;

            foreach (CustomObject v in lst)
            {
                propertyInfos = v.GetType().GetProperties();
                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    column = new DataColumn();
                    column.DataType = System.Type.GetType(propertyInfo.PropertyType.FullName);
                    column.ColumnName = propertyInfo.Name;
                    table.Columns.Add(column);
                }
                //New table made, break the loop
                break;
            }
            //Now populate the table with values
            foreach (CustomObject v in lst)
            {
                 propertyInfos = v.GetType().GetProperties();
                 row = table.NewRow();
                 foreach (PropertyInfo propertyInfo in propertyInfos)
                     row[propertyInfo.Name] = propertyInfo.GetValue(v, null);
                     
                 table.Rows.Add(row);
            }
            return (table);
        }

}

Cheers

11 comments

  1. Terry B

    Beautiful Binu! By far the cleanest and most abstract approach to this issue that I have seen while searching for solutions… Can’t wait to get it a try…

  2. Christian Jensen

    This is great but really does not get everything I want. My objects have DataObjectField attributes on them so that the gridview can pretty much auto populate. Doesn’t using this method just blow that away?

    I would love to see how to create a DataView with attributions so that when the GUI editor picks it up it knows everything about the object.

    Any ideas?

  3. Pingback: dotnet etc.
  4. Pingback: Step by Step – GridView with extras « dotnet etc.
  5. Hemant Tank

    Here’s my original problem which lead me to this thread –
    http://stackoverflow.com/questions/2255269/optimize-pagination-sorting-with-objectdatasource-having-enablecaching-true

    I’ve found some other references like:
    http://www.codeproject.com/KB/aspnet/GridViewObjectDataSource.aspx
    http://forums.asp.net/t/1344883.aspx
    http://forums.asp.net/p/1509071/3676014.aspx#3676014

    But all say that I’ve to perform sorting on app side using the ‘Custom-sort’ (that is add extra methods to enable sorting on a generic collection of objects). This solution was not acceptable because it demanded that I pull ALL the records from the DB and then perform sorting on them!

    Firstly, I don’t believe app can do better/faster sorting then DB. And secondly – this ruins the whole performance benefit that I’m getting due to optimized pagination – I’m using .skip() and .take() LINQ methods to fetch only a ‘pageful’ of records.

    Well, finally I had to invent a fix of my own. It might be limited to my kind of scenario but for sure its much easier and also preserves the optimization of both pagination as well as data-caching.

    MY SOLUTION:
    I’ve tapped the Gridview’s ‘Sorting’ event. The ‘custom-sort’ error triggers if I allow the ODS to try to do the sorting on its own on the cached data. Instead of that, now I perform sorting manually and cancel the sorting-event.
    For this – I just have to make the ‘orderBy’ parameter explicit in ODS and set it to the new sort-expression in Gridview’s ‘Sorting’ event. This will refresh the Grid and at the end I do:

    odsOrganization.SelectParameters[“orderBy”].DefaultValue = GetSortExpr(e.SortExpression);

    e.Cancel = true;

    – this tells the ODS to cancel sorting (which I already performed before canceling the event – as above). ITs like I’m cheating the ODS and handling the sorting in background. And thanks to ODS that it senses that the ‘SelectParameters[“orderBy”]’ has changed and performs a select once again. I The previous sort automatically gets stored in the ‘odsOrganization.SelectParameters[“orderBy”].DefaultValue’ which I can use in sub-sequent iterations.

    I’m still testing this one but its amazing that just by updating the parameter’s DefaultValue ODS goes back to fetch the data. This preserves the cache until the user performs sort (it takes data from cache for other operations) and goes back to the DB to sort. Hope its going to work for me!

  6. Oscar Bautista

    I am getting “contraints are not allowed on non-generic declarations” on line 08. VS is underlying the “where” word. Does anyone know how to resolve this?

  7. Pingback: 2010 in review « dotnet etc.
  8. Mark Orlando

    I am immensely grateful for this posting! I’ve been thrown into a project that requires me to build alot of grids and I am not a front-end developer. Your posting saved my day.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s