Creating Datagrid columns programmatically
By AzamSharp
Views: 21511

 Introduction:

We are all familiar with Datagrid control's bound and template column. Usually we build columns using property builder. In this article I will show that how you can programmatically create bound and template columns of datagrid control.

Why create columns programmatically?

There are lot of situations where creating columns programmatically is more beneficial than creating them using the design view. Suppose that you have a stored procedure that returns several columns from the database. You can use the design view of datagrid to add columns if you know that how many columns are being returned. If you don't know the number of columns returned then creating the columns at runtime will be a better approach.

Creating Bound Columns Dynamically:

Let's see how we can easily create and bind the Bound Columns to the datagrid. We simply create an instance of the BoundColumn class. Then we assigned the HeaderText and DataField property to the bound column and finally we add the columns the Datagrid. 

 

// Create Bound Columns

BoundColumn nameColumn = new BoundColumn();

nameColumn.HeaderText = "Name";

nameColumn.DataField = "UserName";

myDataGrid.Columns.Add(nameColumn);

myDataGrid.DataSource = ds;

myDataGrid.DataBind();

Creating Template Columns Dynamically:

Creating Template columns dynamically is not as easy as Bound columns. Let's see the code below:

 

for ( int i=1 ; i <= dt.Columns.Count -1 ; i++)

{

// Creating Template Column

TemplateColumn test = new TemplateColumn();

string columnName = dt.Columns[i].ColumnName;

test.HeaderTemplate = new DataGridTemplate(ListItemType.Header,columnName);

// Adding the Rows to the DataGrid

for ( int j=0; j<= dt.Rows.Count - 1 ; j++)

{

string score = dt.Rows[j][i].ToString();

test.ItemTemplate = new DataGridTemplate(ListItemType.Item,score);

}

myDataGrid.Columns.Add(test);

}

 

We are running a loop which goes through every item in a DataTable object. Inside the loop we create an instance of the Template column and assign the column name from the datatable to template column header template. Then we have an inner loop which fills the rows from the datatable to the template column items.

You might be wondering that what is "DataGridTemplate". Its a class that is used to generate the column type of the template columns. Let's see small code snippet from that class.

 

public class DataGridTemplate : System.Web.UI.Page,ITemplate

{

ListItemType templateType;

string columnName;

public DataGridTemplate(ListItemType type, string colname)

{

templateType = type;

columnName = colname;

}

The class inherits the "ITemplate" interface which is the same interface that all the datagrid template column uses. "ListItemType" denotes the type of the template that we wish to use.

All the columns are added to the control hierarchy in the InstantiateIn() method. This method is called when ever we bind the grid using the DataBind method.

 

public void InstantiateIn(System.Web.UI.Control container)

{

Literal lc = new Literal();

LinkButton lb = new LinkButton();

switch (templateType)

{

case ListItemType.Header:

lc.Text = "<B>" + columnName + "</B>";

lb.Text = "Edit";

lb.CommandName = "EditButton";

container.Controls.Add(lb);

container.Controls.Add(lc);

break ;

case ListItemType.Item:

lc.Text = "Item " + columnName;

container.Controls.Add(lc);

break ;

case ListItemType.EditItem:

TextBox tb = new TextBox();

tb.Text = "";

container.Controls.Add(tb);

break ;

case ListItemType.Footer:

lc.Text = "<I>" + columnName + "</I>";

container.Controls.Add(lc);

break ;

}

As you can see this class contains different types of ListItemTypes, which is an enumerated type. ListItemType denotes that what action to take for what template. I have made all the ListItemTypes "bold" so you can easily identify them. As you can see if you use editItemTemplate you will get the TextBoxes and for other templates you will get Literal controls.

Where to put the column building code?

It is very important that you place your Datagrid building code in the right place or else it won't work as expected. Here is a bad example of creating a datagrid which is made of dynamic columns.

 

if (!Page.IsPostBack)

{

BuildDataGrid();

}

There is no doubt that if you implemented the BuildDataGrid method without any mistakes than it will show you datagrid on Page Load event. But as soon as the postback happens your grid will be gone. That's why its not the perfect place for the "BuildDataGrid" method.

You should place the BuildDataGrid method in the InitializeComponent method which is called at the very early stages of the Page life cycle.

 

private void InitializeComponent()

{

this .myDataGrid.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler( this .myDataGrid_ItemCommand);

this .Load += new System.EventHandler( this .Page_Load);

// Make the Datagrid

BuildDataGrid();

}

This will ensure that each time the page is created all the controls are created as well.

Conclusion:

Building columns dynamically might be little challenging but it gives you great flexibility to model your columns in any way you like. I hope you liked the article, happy coding !

By AzamSharp


Enter Comment/Feedback
  •  
  •  
  •  
  •  
  •  

Comments/Feedbacks
Subject: Creating Datagrid columns programmatically
Name: Mr. Long K. Trinh
Date: 2/1/2007 2:42:20 PM
Comment:
Thank you for sharing your knowledge.

But on this sample,I cannot make it work.
//
My background: Quite new on developing web apps, but willing to learn. Started with VS2003 (DataGrid) for less than 2 months then switched to VS2005 (GridView.) Find it hard to learn the new GV control using old samples built on DG control.
///
How can I make old samples using DataGrid work as GridView control? Thanks. lkt.
Subject: is there another way of recreating controls
Name: John
Date: 4/16/2007 11:43:53 AM
Comment:
I have this working in 2005 and with the GridView. I have an issue with finsing controls. I can not put the creation in the page init. I create the grid after the page has loaded and after the user made a selection from a ddl. when I go to save the findcontrol fails they are not there.

can i recreate the controls again with the changed data from the user?
Subject: abt ur sample
Name: yogarajan
Date: 5/4/2007 4:43:02 AM
Comment:
i have download ur source code but i got error

error disc:
Could not load type 'Glasses.Test.DataGridEditColumn'.

pls help me
Subject: GridView Control
Name: Senthilmurugan
Date: 5/15/2007 1:33:39 AM
Comment:
Hi,
I want the same functionality which is created in GridView Class.

My req is to create GridView dynamically and add column dynamically and Format the column dynamically.

Is there any sol?
Subject: template column is gone after postback
Name: ali
Date: 1/31/2008 4:19:28 AM
Comment:
The template column will disappear after any postback. Is there any solution?
Subject: But how can one add a button to put the row into edit mode?
Name: Perry
Date: 2/26/2008 3:10:25 PM
Comment:
I've been Googling for some time on how to add a button that puts the row into edit mode. I've seen a bunch of examples such as yours, but so far nobody has shown how to trigger the grid to fire its ItemCommand event. Any clues? Reflector isn't helping me much on this issue. It appears that design time template columns can and due hook up somehow internally so that the ItemCommand event on the grid the template column is on if there's a Button or LinkButton. See below. It builds the display properly but doesn't fire the ItemCommand event for the grid...


public class EditCancelControl : System.Web.UI.ITemplate
{
protected ListItemType lit;
protected string headerName;

public EditCancelControl(System.Web.UI.WebControls.ListItemType type,
string HeaderName)
{
lit = type;
headerName = HeaderName;
}

public EditCancelControl(System.Web.UI.WebControls.ListItemType type)
{
lit = type;
headerName = "";
}

public void InstantiateIn(System.Web.UI.Control container)
{
Button btn;
switch (lit)
{
case ListItemType.Header:
Label lbl = new Label();
lbl.Text = headerName;
container.Controls.Add(lbl);
break;
case ListItemType.Item:
btn = new Button();
btn.ID = "btnEdit";
btn.Text = "Edit";
btn.CommandName = "Edit";
btn.CssClass = "SmallTextButton";
btn.CausesValidation = false;
container.Controls.Add(btn);
break;
case ListItemType.EditItem:
btn = new Button();
btn.ID = "btnCancel";
btn.Text = "Cancel";
btn.CommandName = "Cancel";
btn.CssClass = "SmallTextButton";
btn.CausesValidation = false;
container.Controls.Add(btn);

container.Controls.Add(new LiteralControl("nbsp;"));

btn = new Button();
btn.ID = "btnUpdate";
btn.Text = "Update";
btn.CommandName = "Update";
btn.CssClass = "SmallTextButton";
btn.CausesValidation = false;
container.Controls.Add(btn);
break;
}
}
}

public class EditCancelTemplate : TemplateColumn
{
public EditCancelTemplate(string Name, DataGrid Grid)
{
this.EditItemTemplate = new EditCancelControl(ListItemType.EditItem);
this.HeaderTemplate = new EditCancelControl(ListItemType.Header, Name);
this.ItemTemplate = new EditCancelControl(ListItemType.Item);
Grid.Columns.Add(this);
}
}
Subject: RE: But how can one add a button to put the row into edit mode?
Name: AzamSharp
Date: 2/26/2008 7:42:46 PM
Comment:
Hi Perry, Where are you attaching the Row_Command event. You need to do something like: gv_RowCommand+= [event handler] to attach the event.
Subject: RowCommand event
Name: Perry
Date: 2/27/2008 10:02:46 AM
Comment:
Thanks for a speedy reply. As you can see, I am not attaching to any RowCommand event. I intuited that I would need to do something like that, to trigger the fact that an event occured on a particular row, but could not find any such event both in .NET documentation as well as through inspection of objects through Reflector. So, what object exposes that event? (DataGrid? I can't find any...) And what object in my example would need to trigger that event? (one of my buttons?)

Subject: RE: RowCommand Event
Name: AzamSharp
Date: 3/1/2008 7:51:01 AM
Comment:
Hi Perry, Since, you are using Datagrid you will have to use the ItemCommand event which is fired whenever any event takes place inside the Datagrid control.
Subject: Multiple Users - Wrong row selected
Name: pliant
Date: 5/16/2008 10:31:58 AM
Comment:
Because the datagrid is databinding each time the page loads, if one users deletes a row and another user goes to edit\delete a row after that the wrong row is deleted\edited because the row index is out of sync with the data it is now bound to. Is there any way around this issue?



Join WebHost4Life.com






Copyright GridViewGuy 2007-2008