Implementing multi-column headers in WebDataGrid

The Infragistics ASP.NET WebDataGrid control comes with the option to add multi-column headers – much like grouping your actual columns. These headers let you structure your grid data in a meaningful way , making it easy for the end-user to quickly locate the information he’s looking for. Using this additional layer of columns requires no overhead and reorganizing of your data. This blog will focus on showing you how to go about implementing the multi-column headers and , as you shall hopefully realize by its end , it’s not a tedious task after all.

Let’s get on with it !

How to do it

Starting with a fresh WebDataGrid , there is very little you need to do in order to prepare it for utilizing GroupFields – these are the multi-column headers we’ve been talking about.

Here’s an example of what your grid setup might look like prior to the inclusion of the group fields:

   1: protected void Page_Load(object sender, EventArgs e) {
   2:     if (!this.Page.IsPostBack) {
   3:         BoundDataField field = new BoundDataField();
   4:         field.Key = "FirstName";
   5:         field.DataFieldName = "FirstName";
   6:         field.Header.Text = "First Name";
   7:         this.dataGrid.Columns.Add(field);
   8:  
   9:         field = new BoundDataField();
  10:         field.Key = "LastName";
  11:         field.DataFieldName = "LastName";
  12:         field.Header.Text = "Last Name";
  13:         this.dataGrid.Columns.Add(field);
  14:  
  15:         field = new BoundDataField();
  16:         field.Key = "Age";
  17:         field.DataFieldName = "Age";
  18:         field.Header.Text = "Age";
  19:         this.dataGrid.Columns.Add(field);
  20:  
  21:         field = new BoundDataField();
  22:         field.Key = "Address";
  23:         field.DataFieldName = "Address";
  24:         field.Header.Text = "Address";
  25:         this.dataGrid.Columns.Add(field);
  26:  
  27:         field = new BoundDataField();
  28:         field.Key = "Country";
  29:         field.DataFieldName = "Country";
  30:         field.Header.Text = "Country";
  31:         this.dataGrid.Columns.Add(field);
  32:  
  33:         this.dataGrid.Behaviors.Add(new Activation());
  34:         this.dataGrid.Behaviors.Add(new ColumnMoving());
  35:     }
  36: }

There is nothing fancy going on in these lines. We have a number of data fields which represent our columns. The check performed on line 2 is cause of the custom behaviors added – since they operate on postbacks , we do not want to try to add the fields again every time the columns are reordered , for example. It will not work anyway. The instantiation of the grid’s data source happens in the OnInit method , that’s why you don’t see it here.

Now here’s the same grid , with two multi-column headers added – one is labeled “Personal Info” and contains the first three columns , the other one is called “Additional Info” and contains the remaining two columns.

   1: protected void Page_Load(object sender, EventArgs e) {
   2:     if (!this.Page.IsPostBack) {
   3:         GroupField group = new GroupField();
   4:         group.Header.Text = "Personal Information";
   5:         group.Key = "PersonalInfo";
   6:  
   7:         BoundDataField field = new BoundDataField();
   8:         field.Key = "FirstName";
   9:         field.DataFieldName = "FirstName";
  10:         field.Header.Text = "First Name";
  11:         group.Columns.Add(field);
  12:  
  13:         field = new BoundDataField();
  14:         field.Key = "LastName";
  15:         field.DataFieldName = "LastName";
  16:         field.Header.Text = "Last Name";
  17:         group.Columns.Add(field);
  18:  
  19:         field = new BoundDataField();
  20:         field.Key = "Age";
  21:         field.DataFieldName = "Age";
  22:         field.Header.Text = "Age";
  23:         group.Columns.Add(field);
  24:  
  25:         this.dataGrid.Columns.Add(group);
  26:  
  27:         group = new GroupField();
  28:         group.Header.Text = "Additional Information";
  29:         group.Key = "Additional";
  30:  
  31:         field = new BoundDataField();
  32:         field.Key = "Address";
  33:         field.DataFieldName = "Address";
  34:         field.Header.Text = "Address";
  35:         group.Columns.Add(field);
  36:  
  37:         field = new BoundDataField();
  38:         field.Key = "Country";
  39:         field.DataFieldName = "Country";
  40:         field.Header.Text = "Country";
  41:         group.Columns.Add(field);
  42:  
  43:         this.dataGrid.Columns.Add(group);
  44:         this.dataGrid.Behaviors.Add(new Activation());
  45:         this.dataGrid.Behaviors.Add(new ColumnMoving());
  46:     }
  47: }

The changes here are the addition of two GroupField objects – lines 3 to 5 and then 27 to 29. You may also notice the pattern of work with these objects. Instead of adding your actual columns directly to the WebDataGrid , you add them to the corresponding GroupField object’s Columns collection ( just like how you would add them directly to the WebDataGrid – lines  11 , 17 , 23 , 35 , 41 ). Then , when the GroupFields have been “loaded” with columns , you add each one to your WebDataGrid’s Columns collection – as seen on lines 25 and 43.

 

Here’s what the setup above would look like if you specified your columns with the ASP.NET syntax:

   1: <Columns>
   2:     <ig:GroupField Key="PersonalInfo">
   3:     <Header Text="Personal Info" />
   4:         <Columns>
   5:             <ig:BoundDataField Key="FirstName" DataFieldName="FirstName">
   6:                 <Header Text="First Name" />
   7:             </ig:BoundDataField>
   8:             <ig:BoundDataField Key="LastName" DataFieldName="LastName">
   9:                 <Header Text="Last Name" />
  10:             </ig:BoundDataField>
  11:             <ig:BoundDataField Key="Age" DataFieldName="Age">
  12:                 <Header Text="Age" />
  13:             </ig:BoundDataField>
  14:         </Columns>
  15:     </ig:GroupField>
  16:     <ig:GroupField Key="AdditionalInfo">
  17:     <Header Text="Additional Info" />
  18:         <Columns>
  19:             <ig:BoundDataField Key="Address" DataFieldName="Address">
  20:                 <Header Text="Address" />
  21:             </ig:BoundDataField>
  22:             <ig:BoundDataField Key="Country" DataFieldName="Country">
  23:                 <Header Text="Country" />
  24:             </ig:BoundDataField>
  25:         </Columns>
  26:     </ig:GroupField>
  27: </Columns>

The same idea is seen in the code above – instead of directly adding the BoundDataFields directly to the Columns , you add them to a GroupField instead.

As with all other “Key” attributes , the one belonging to the GroupField should also be unique and not empty.

You can see the official examples on multi-column layouts by checking out this link.

Additionally , you may also download the sample project by clicking here.


Comments  (1 )

sportfish1850
on Wed, Mar 28 2012 2:16 PM

Jordan-

I had implemented multi-column headers just as you described, and they worked flawlessly until I installed the most recent service update (2086) yesterday.  

Now, the grid renders correctly, but whenever I click on a row or a button in a cell, I receive an IndexOutOfRange exception.  

I have narrowed it down to the use of GroupFields.  I define the column layout at runtime.  Without GroupFields I get no exception.  With the GroupFields, I get the exception.

Any thoughts?  The ONLY change was updating to the most current controls.

Add a Comment

Please Login or Register to add a comment.