ASP.NET AJAX Hierarchical Data Grid Multi-Column Headers

Damyan Petev / Thursday, June 7, 2012

A multi-column header feature has been available thus far only for the flat data ASP.NET AJAX grid and I believe there’s barely anyone left wondering what that would do. Call it grouped headers, merged headers - aside from the obvious aesthetics having column headers grouped (well, perhaps not so obvious – I like it at least) there’s a very practical functionality at play here – it’s about customization and it’s about ease of digesting data. It would be much easier to get your way around  a table that has column headers stacked in neat groups. Then the groups can be in groups and so on – basically order rules the lands!


The otherwise already feature-rich WebHierarchicalDataGrid control got a a bit richer – with the latest release such feature was introduced to the hierarchical data grid (following the flat data grid’s lead) so now you can hierarchy in both your data and your columns. The headers visually and logically (and you will see below very much functionally so, too) group together columns:

Root and child bands with multi-column headers.

In the above screenshot the hierarchical grid has the root layout (band) column headers grouped in two main categories – Company and Location information and nested logical groups in those as well. The child bad headers are all in a single group that serves as a title if you will and also have nested logical grouped inside. Also note I may have gone too far grouping almost everything, but that’s to show off the feature and real-life applications may use this in a more restrained manner based on design requirements.

Getting Started

I’ll demonstrate how easy it is to use (refer to the following help topic should you need help getting started with the Web Hierarchical Grid ), but before that a shot theory of operation – the multi-column headers are based on the way the columns are defined, which is to say this feature is not a behaviour you might find in the grid options.

Actually there’s a new ‘column’ type available in the grid now – the Group Field. Think of it like a unbound column (still requires a key) that will hold other columns and it’s header will be on top of all of them. And in terms of adding the group field you can treat it like a normal column you add to a band collection or column collections of other group fields. This is 100% doable through the grid’s smart tag menu:

Group field with Columsn collection in the smart tag menu.

As you can see this is the Edit Columns menu of a band (root in this blog’s demo) and you can add a Group Field to the columns collection and the field itself has such collection where you can add your actual bound fields and other group if you need. Of course, this can be done in code as well and it is valid for both root and child layouts. Below is the full snippet for the layout Using the Northwind’s Customers and Orders tables.

  1. <ig:WebHierarchicalDataGrid ID="WebHierarchicalDataGrid1" runat="server" Height="500px"
  2.         Width="650px" DataSourceID="WebHierarchicalDataSource1" StyleSetName="IG" AutoGenerateColumns="False"
  3.         DataKeyFields="CustomerID">
  4.         <Columns>
  5.             <%-- Grouped headers/columns in main layout--%>
  6.             <%--Company Group--%>
  7.             <ig:GroupField Key="ParentGroup" Header-Text="Company">
  8.                 <Columns>
  9.                     <ig:BoundDataField DataFieldName="CompanyName" Key="CompanyName" Header-Text="Company Name" />
  10.                     <ig:GroupField Key="ChildGroup" Header-Text="Contact">
  11.                         <Columns>
  12.                             <ig:BoundDataField DataFieldName="ContactName" Key="ContactName" Header-Text="Name" />
  13.                             <ig:BoundDataField DataFieldName="ContactTitle" Key="ContactTitle" Header-Text="Title" />
  14.                             <ig:BoundDataField DataFieldName="Phone" Key="Phone" Header-Text="Phone" />
  15.                         </Columns>
  16.                     </ig:GroupField>
  17.                     <ig:BoundDataField DataFieldName="Fax" Key="Fax" Header-Text="Fax" />
  18.                 </Columns>
  19.             </ig:GroupField>
  20.             <%--Location Group--%>
  21.             <ig:GroupField Key="ParentGroup2" Header-Text="Location">
  22.                 <Columns>
  23.                     <ig:BoundDataField DataFieldName="Country" Key="Country" Header-Text="Country" />
  24.                     <ig:GroupField Key="ChildGroup2" Header-Text="Full Adress">
  25.                         <Columns>
  26.                             <ig:BoundDataField DataFieldName="Address" Key="Address" Header-Text="Address" />
  27.                             <ig:BoundDataField DataFieldName="City" Key="City" Header-Text="City" />
  28.                             <ig:BoundDataField DataFieldName="PostalCode" Key="PostalCode" Header-Text="PostalCode" />
  29.                         </Columns>
  30.                     </ig:GroupField>
  31.                 </Columns>
  32.             </ig:GroupField>
  33.         </Columns>
  34.         <Bands>
  35.             <ig:Band AutoGenerateColumns="False" DataKeyFields="OrderID" Key="Orders" DataMember="EntityDataSource2_DefaultView">
  36.                 <Columns>
  37.                     <%--Child Layout Group--%>
  38.                     <ig:GroupField Key="Group" Header-Text="Order shipping">
  39.                         <Columns>
  40.                             <ig:BoundDataField DataFieldName="ShipVia" Key="ShipVia" Header-Text="Ship via" />
  41.                             <ig:BoundDataField DataFieldName="ShipName" Key="ShipName" Header-Text="Ship Name" />
  42.                             <ig:GroupField Key="ChildGroup3" Header-Text="Ship Dates">
  43.                                 <Columns>
  44.                                     <ig:BoundDataField DataFieldName="OrderDate" Key="OrderDate" Header-Text="Order Date" />
  45.                                     <ig:BoundDataField DataFieldName="RequiredDate" Key="RequiredDate" Header-Text="Required Date" />
  46.                                     <ig:BoundDataField DataFieldName="ShippedDate" Key="ShippedDate" Header-Text="Shipped Date" />
  47.                                 </Columns>
  48.                             </ig:GroupField>
  49.                         </Columns>
  50.                     </ig:GroupField>
  51.                 </Columns>
  52.             </ig:Band>
  53.         </Bands>
  54.         </ig:WebHierarchicalDataGrid>

And the end result is the screenshot above. Note the Keys on group fields are unrelated to your data, they are required for future referencing the fields.


A very curtail part for such a feature to work well is how it would cooperate with other features that depend on the columns’ size/position/header in some way. As mentioned, the Multi-column headers are a feature dependant on column definitions and not a behaviour, therefore dependant behaviours have been altered instead to be mindful of that and ‘behave’ properly. Such features are:

  • Sorting – naturally sorting remains on the actual column header (like the Name column below) and clicking the group headers does not activate a sort action attempt:

Column sorting on the nested headers.

  • Selecetion – when Selection behaviour is active with Column selection enabled, normal headers work as expected and group headers select the first of their nested group when clicked.
  • Resizing – resizing also works as expected, modifying the size of a nested column will modify the size of the group field and vice versa.
  • Moving – Column moving is a very interesting interaction. The behaviour will respect the defined groups and will only allow moving of columns in their respective ‘level’.

Column moving only allowed on the same group level.

Also moving will work with dragging group headers just like with normal ones and will move the whole group.

  • Filtering  - as seen above and just like sorting the filtering UI will be tied to the actual column headers and function normally.


The ASP.NET AJAX Hierarchical Data Grid’s new Multi-Column Headers feature lets developers organize data columns within categories for users to easily read through. It’s both visually pleasing and functional and very easy to define via the Group Filed object. Several column related behaviours have also been adjusted to work properly with multi-column headers and obey the columns’ grouping.

Download the demo project for this blog to try for yourself or visit the ASP.NET AJAX Hierarchical Data Grid’s Multi-Column Headers Online Sample. As always, you can follow us on Twitter @DamyanPetev and @Infragistics and stay in touch on Facebook, Google+ and LinkedIn!