INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

Code Examples

How to add template columns to a DataGrid by code by JCruz063
Posted: 20 Feb 04 (Edited 23 Feb 04)

Introduction
As we all know, the DataGrid web server control is, by far, the most powerful of the intrinsic .NET web server controls. One of the reasons why this is the case is that the DataGrid allows the programmer to perform complex tasks such as editing, paging, among others, with miminum code. Template columns are another one of the niceties that makes the DataGrid so great. With template columns, controls could be added within the cells of the DataGrid to allow a level of flexibility that is simply to good to pass by unnoticed.

While there are tons of sources that describe how to implement template columns at design time, very few exist that talk about how template columns could be implemented at run time. Implementing template columns at run time is the topic of this FAQ.

Note: The reason why I needed to implement template columns at run time is that my application displays a grid with text boxes that allow the user to select data he is interested in. Each column in the grid would be composed of check boxes for the user to make his selections. Now, the number of columns varies depending on the user and thus I would only know at run time how many columns the grid would have. Therefore, I needed a way to simply create the template columns at run time, depending on the user that was logged on to my site.

About the ITemplate Interface...
Creating a template column at run time is very simple.  The general approach is the following:

CODE


TemplateColumn tc = new TemplateColumn();
tc.HeaderText = [Text of column header];
tc.ItemTemplate = [ITemplate type];
// dg is the DataGrid control
dg.Columns.Add(tc);

As you can see from the above code snippet, you simply create a TemplateColumn variable, give values to its Text and ItemTemplate properties and you're ready to go. The important part lies in the type of the ItemTemplate property. As you can see, this must be a class that supports the ITemplate interface. Thus, adding a template column to a grid at run time will consist of creating a class that implements the ITemplate interface. We will see how to create such a class.

Now, the ITemplate interface has only one method, InstantiateIn. This method is called when a new instance of the template column is created. It takes one parameter of type System.Web.UI.Control which represents the container control that hosts the controls within the template column. Thus, this method is where you would create the controls that you would like displayed in your template column. In my case, I needed a check box in my template column thus  my class looks like this:

CODE


private class CheckBoxTemplate : ITemplate
{        
  // Implementation of ITemplate
  public void InstantiateIn(System.Web.UI.Control container)
    {    
      // Create a check box
      CheckBox cb = new CheckBox();
      // Make the check box appear
      // in the column

      container.Controls.Add(cb);
    }
}
    

That's it! This is all you need to create a template column for a DataGrid at run time. As you may suspect, you can set the properties of the text box (or whatever control you create) in whatever way you like. Also, you're not limited to adding just one control, but you can add as many as you want. Now, tell me that's not cool...

Data Biding
But that's not all! The interesting stuff gets even more interesting when you add data binding to the controls you create in InstantiateIn. To implement data binding, you would have to write code to the DataBinding event of the controls you create. The event handling mechanism is the same used in Web and Windows forms: You create a method with the same signature of the delegate of the event and then add the method to the delegate. This is how the class looks now (new code is in bold).

CODE


private class CheckBoxTemplate : ITemplate
{        
  public void InstantiateIn(System.Web.UI.Control
  container)
  {
    // Create a check box
    CheckBox cb = new CheckBox();
    //Attach method to delegate
    cb.DataBinding +=
    new System.EventHandler(this.BindCheckBox);

    container.Controls.Add(cb);
  }

  //Method that responds to the
  DataBinding event
    
  private void BindCheckBox(object sender,
  System.EventArgs e)
  {
    CheckBox cb = (CheckBox)sender;
    DataGridItem container =
    (DataGridItem)cb.NamingContainer;    
    cb.Checked = [Data binding expression];    
  }
}
As you can see, the InstantiateIn method has one new line of code:

CODE


cb.DataBinding +=
   new System.EventHandler(this.BindCheckBox);

All this does is it attaches the BindCheckBox method to the DataBinding event of the check box. The delegate of the DataBinding event has two arguments: sender, which is of type object and e, which is of type EventArgs (We really don't need e for data binding). sender represents the check box that is being bound, and that's why I have the line:

CODE

CheckBox cb = (CheckBox)sender;

which simply gets a reference to such CheckBox. Now, the NamingContainer property of the check box represents the DataGridItem (in other words, the row) of the grid where the CheckBox control is. Thus with the following line, I get a reference to the row of the grid where the CheckBox is:

CODE

DataGridItem container =
(DataGridItem)cb.NamingContainer;

Finally, assuming that the DataGrid control is bound to some data source that has a field named "ItemID", we could write a data binding expression using DataBinder.Eval method. The line below (which is not in the code above) sets the Checked property of the CheckBox to true if the "ItemID"; of the datasource is 10.

CODE

cb.Checked =
(DataBinder.Eval(container.DataItem, "ItemID").ToString() == "10";);

In case you don't know what the Eval method is, it's simply a method that takes in a DataGridItem (i.e. a row in the DataGrid) and a string representing a field in such row, and returns, as an object, the value for the such field in the such row.

Of course, your data binding expressions could be as complex as you want. In this method, you could literally do anything...

Finally, the line which is missing for the very first code snipped shown here is the following (in bold):

CODE


TemplateColumn tc = new TemplateColumn();
tc.HeaderText = [Text of column header];
//Isn't this beautiful?
tc.ItemTemplate = new CheckBoxTemplate();
// dg is the DataGrid control
dg.Columns.Add(tc);

Cool, eh?

Conclusion
You may may want to keep the follow two points in mind:
1 - The class that implements the ITemplate interface is very simple and maybe implemented as a private class within the page where it will be used. However, this doesn't have to be so. You may add complexity to this class by using overloaded constructors that may set initial settins to set the appearance of the controls in the template columns.

2 - You should call the DataGrid's DataBind method after you have added the template columns.

That's all folks! If you read this FAQ and have problems understanding it, you may write me at cuchy063@hotmail.com

JC

Back to C# (C sharp): Microsoft FAQ Index
Back to C# (C sharp): Microsoft Forum

My Archive

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close