Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Sortable, Generic GridView with Paging Capabilities

3.25/5 (4 votes)
26 Nov 2008GPL34 min read 1   530  
Sortable, Generic GridView with paging capabilities with ready outlook and number formatting

Introduction

Sometimes you really need to have a dynamic GridView object. I mean no declarative code, just something like:

C#
GridView gv = new GridView () ; 
panelGvHolder.Controls.Add( gv ) ; 

Background

Most of the original code is from the Alex Furmanski's Extended GridView with Insert Functionality. The idea of sorting and paging is from Strong Coders. The formatting idea is from Mike Ellison's Formatting AutoGenerateColumns in an ASP.NET Grid. So herewith, I would like to thank those guys for sharing their brilliant ideas and try to wrap up / bring something additional such as the convenience to have a really GENERIC GridView. For legal disclaimer lovers - I have the bad habit of copy, pasting and playing with code at 03:00 AM so if you find your code or someone else's code, just mail me and I'll fix it ...

Ok what is this generic then? Why is it so important? Well keep reading and you will never have to bother remembering and coding those column names from your datatables (when your colleagues from the database side change the database, as long as the name of the datatable stays the same, you will not have to do any recoding.

Using the Code

My development environment is Windows Vista, Microsoft .NET Framework Version 3.5, Microsoft Visual Studio 2008. I have also tested this control on Visual Studio 2005 and .NET 2.0. and Windows XP. So, what to do?! Just download the zip. Unpack it and compile first the XGrid control (in the XGrid folder) by pressing Ctrl + B and then the TestWeb project by pressing Shift + F5, F5.

See the XGridTestSite project for how to create and where to pass your datatable, so for demonstration purposes, I do use just datatable generation. (I hate those examples using Microsoft Adventure Works database - one has always to install and configure something and it takes hours before getting something meaningful out of a simple example.)

If you like direct action, just copy paste the following two files - XGrid.cs and Formatter.cs into your App_Code directory and instead of using declarative code ( <asp:GridView ID="gv" ... ), just write in the method where you create the dynamic controls:

C#
GUI.Controls.XGrid gv = new GUI.Controls.XGrid ( ); 

Later on just assign a datatable to it and call DataBind on it ... actually the exact way to implement is presented below:

So here is the data population method you should change according to your requirements:

C#
private void PopulateRds ( )
{
    //PUT YOUR CODE HERE TO GET THE DATASET OBJ / DATATABLE OBJ
    DataSet rds = new DataSet ( );
    DataTable dt = new DataTable ( "myDynamicTable" );
    // Create DataColumn instances

    DataColumn dId = new DataColumn ( );
    DataColumn dName = new DataColumn ( );
    DataColumn dDecimal = new DataColumn ( );

    dId.ColumnName = "Id";
    dId.DataType = Type.GetType ( "System.Int32" );

    dName.ColumnName = "Name";
    dName.DataType = Type.GetType ( "System.String" );

    dDecimal.ColumnName = "Decimal";
    dDecimal.DataType = Type.GetType ( "System.Double" );

    // Add these DataColumns into the DataTable
    dt.Columns.Add ( dId );
    dt.Columns.Add ( dName );
    dt.Columns.Add ( dDecimal );

    for ( int i = 0 ; i< 20 ; i++ )
    {
        DataRow dr = dt.NewRow ( );
        dr ["Id"] = i;
        dr ["Name"] = "Name " + System.Convert.ToString ( i );
        dr ["Decimal"] = 2222221.3333;
        // Add the row into the table

        dt.Rows.Add ( dr );
    }
    rds.Tables.Add ( dt );

    Session [ "dt"] = rds.Tables [0];

} //eof method PopulateDataTable

And this is how you create your own extended gridview:

C#
    private void CreateDynamicControls()
{
    this.PopulateRds();
    for ( int i = 0 ; i<9 ; i++ )
    {
        GUI.Controls.XGrid gv  = new GUI.Controls.XGrid ( );
        gv.DataSource = Session ["dt"];
        gv.AllowSorting = true;
        gv.ShowResultSummary = true;
        gv.AllowPaging = true;
        gv.ID = i.ToString ( ) + i.ToString();
        gv.AutoGenerateColumns = true;
        gv.DataBind ( );
        panGvHolder.Controls.Add ( gv );

    } //eof for method CreateDynamicControls

Oops, I did 9 of those;), but you get the idea - it is really dynamic ... So, yes you do not need to care about the events of one XGrid obj interfering with the next one on the page.

Update for Using Helper Method for Real Gridview

I noticed that if you have to deal constantly with fully dynamic gridviews, your hunger grows and you start to implement some helper methods. Here is my helper one:

C#
public static void PrepListingWithSizeAndIndex ( ref string msg, 
ref GUI.Controls.XGrid gv,
ref System.Data.DataSet rds, int flagPageSize , int index)
{
  try
  {
   if ( rds == null || gv == null || 
rds.Tables [0] == null )
{
msg = " No data found ";
//this method just populates an empty one ...
Utils.Data.DataSetGastArbeiter.PopulateMsgDataSet ( ref msg );
gv = new GUI.Controls.XGrid ( );
gv.Visible = true;
gv.DataBind ( );
return;
}
if ( gv != null )
{
//Utils.Debugger.DebugDataSet("From PrepareSimpleListingGV tracking rds ", ref rds);
//|	if ( rds.Tables [0] == null )
//{
//generate an empty one 
//	Utils.Data.DataSetGastArbeiter.GenerateEmptyDataSet ( ref rds );
// }
gv.DataSource = rds.Tables [0];
gv.AutoGenerateColumns = true;
gv.AllowPaging = true;
gv.AllowSorting = true;
gv.ShowResultSummary = true;
//do not do this !!!
//gv.PageIndex = 0;			//
gv.PageIndex = index ;   //now when this is session variable and paging works!!!!
gv.EnableSortingAndPagingCallbacks = true;
gv.Visible = true;
gv.PageSize = flagPageSize;
gv.DataBind ( );
} //eof if (gv != null ) 
  else
{
throw new Utils.CustomException ( "a null gv was passed !!!" );
 }
}
catch ( System.IndexOutOfRangeException io )
{
msg = " No data found ";
Utils.Data.DataSetGastArbeiter.PopulateMsgDataSet ( ref msg );
gv = new GUI.Controls.XGrid ( );
gv.Visible = true;
gv.DataBind ( );
return;
eof  catch 
		} //eof method

Points of Interest

I would like to insert a textbox in the paging to be able to set the page size. There are a couple of interesting articles hanging around, but I really haven't had time to implement something for this control.

I would like to get the insert functionality in a generic manner (e.g. whatever table from database is used as a datasource to be able to present it and perform edit, insert, update only by knowing its name and using table metadata....

Actually I have created my own version of object - relational mapping applicable for insert, delete, update on a generic gridview, unfortunately it is kind of buggy and not for show ... yet;). So anybody willing to collaborate just mail me - firstname.lastname@gmail.com.

Limitations of the Control

This control has not been tested on a huge load, so before putting on one consider testing...

  • For huge amounts of data to retrieve consider custom paging - there are good articles around for how to implement one ... and don't forget to share the solution with all of us;).
  • No cookieless, JavaScriptless implementation. If you invent one, please share with the rest of us.
  • No insert, edit, update events working (Even there in the code ... ). Check out Alex Furmanski's example on CodePlex ...
  • No dynamic custom templates available - for this restriction later on another article, if time allows it;). Actually nothing stops you from implementing one on the top of this control. If you do it, do not forget the less clever (like me) to send a link for it ...

History

  • 2008.08.10. -- First publishing - sorting, paging, Outlook formatting and formatting for decimal numbers - ok.
  • 2008.08.12. -- Update on restrictions - Added short list of limitations of the control as pointed out justifiably by readers

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)