Introduction
Sometimes you really need to have a dynamic GridView
object. I mean no declarative code, just something like:
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:
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:
private void PopulateRds ( )
{
DataSet rds = new DataSet ( );
DataTable dt = new DataTable ( "myDynamicTable" );
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" );
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;
dt.Rows.Add ( dr );
}
rds.Tables.Add ( dt );
Session [ "dt"] = rds.Tables [0];
}
And this is how you create your own extended gridview
:
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 );
}
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 gridview
s, your hunger grows and you start to implement some helper methods. Here is my helper one:
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 ";
Utils.Data.DataSetGastArbeiter.PopulateMsgDataSet ( ref msg );
gv = new GUI.Controls.XGrid ( );
gv.Visible = true;
gv.DataBind ( );
return;
}
if ( gv != null )
{
gv.DataSource = rds.Tables [0];
gv.AutoGenerateColumns = true;
gv.AllowPaging = true;
gv.AllowSorting = true;
gv.ShowResultSummary = true;
gv.PageIndex = index ;
gv.EnableSortingAndPagingCallbacks = true;
gv.Visible = true;
gv.PageSize = flagPageSize;
gv.DataBind ( );
}
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
}
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