I used DBauer’s HiraraGrid (http://aspalliance.com/articleViewer.aspx?aId=21&pId=) control for some time now and I thought I’d give it justice by demonstrating how it worked for a kiosk site I used to work on.
My development goal was to create a simple FAQ section of the website wherein answers to questions can be expanded and collapsed real time.

Setting up the Datasource
To make it quick and simple I used xml to store text data in the following manner.
<?xml version="1.0" encoding="utf-8" ?>
<!--
/* USER-DEFINED HTML TAGS FOR FORMATTING */
Customized Tag Equivalent
*************** *****************
[break_here] line break
[bold] start bold
[end_bold] end bold
[italic] start italic
[end_italic] end italic
-->
<faqs>
<faq_set id="0">
<question id="0">
1) How much will I be charged for calls/SMS made while roaming?
</question>
<answer question_id="0">
Roaming calls/SMS/surfing are premium international services and are based on
the roaming charges of the Roaming Partner.
[break_here]
Each Roaming Partner may have different
rates for different roaming services (please refer to the Inter-Operator Tariff Matrix
roaming rates of our Roaming Partners.
</answer>
</faq_set>
<faq_set id="1">
<question id="1">
2) What are the basic components of roaming charges?
</question>
<answer question_id="1">
Roaming charges consist of the airtime rates imposed by the Visited Network,
plus a 15% service charge.
[break_here][break_here]
For calls received while roaming, there are two components,
the SMART IDD rate to the country where the subscriber
is roaming plus the incoming call charge of the Visited Network +15%.
</answer>
</faq_set>
I used a couple of custom “tags” that will be rendered to a corresponding HTML tag in the future. I had this in mind because the project was ultimately going to be turned over to a non-technical content manager hence the need for a more human-readable custom tags. Of course, there's
no stopping the developer from developing his or her own customized tags.
Declaring the HierarGrid
Registering at the page declaration:
<%@ Register
TagPrefix="COLLAPSIBLE_GRID"
Namespace="DBauer.Web.UI.WebControls"
Assembly="DBauer.Web.UI.WebControls.HierarGrid"
%>
The collapsible grid:
<COLLAPSIBLE_GRID:HierarGrid
id="gridFAQs"
runat="server"
CellPadding="3"
AutoGenerateColumns="False"
BackColor="#FFF7E7"
BorderColor="#DEBA84"
BorderStyle="None"
OnItemDataBound="grid_databound"
BorderWidth="1px"
CellSpacing="1"
GridLines="None"
Font-Names="Arial"
Font-Size="XX-Small"
Width="490px"
LoadControlMode="UserControl"
TemplateDataMode="Table"
OnTemplateSelection="gridFAQs_templateSelection"
>
<ItemStyle BackColor="white"
ForeColor="#8C4510" />
<HeaderStyle
BackColor="#A55129"
Font-Bold="True"
ForeColor="White" />
<Columns>
<COLLAPSIBLE_GRID:HierarColumn/>
<asp:TemplateColumn visible="false">
<itemtemplate>
<asp:Label
text='<%# Bind("id") %>'
id="h_questionID"
runat="server"/>
</itemtemplate>
</asp:TemplateColumn>
<asp:TemplateColumn
headerText="Frequently Asked Questions">
<HeaderStyle Font-Size="XX-Small" />
<itemtemplate>
<asp:Label
id="lbl_answer"runat="server"/>
</itemtemplate>
</asp:TemplateColumn>
</Columns>
</COLLAPSIBLE_GRID:HierarGrid>
Some noteworthy properties:
1. LoadUserControl – the format the child item will take. Usually best to set the value to UserControl meaning the expanded items will come from an .ascx file.
2. TemplateDataMode – enumeration. Possible values are “none”, “runtime”, “singleRow” and “table”. I haven’t tried the other variants yet, but usually “table” has always worked fine.
3. OnTemplateSelection – an event. Fired when the user clicks on the “+/-“ image icon.
4. HierarColumn – The icon column that will contain “+/-“. Usually stored in ~Images/ root directory and is named “plus.gif” and “minus.gif”.
Programming the HierarGrid
private string xmlPath = "";
private DataSet DS_faqs = new DataSet();
private DataColumn parentDC, childDC;
private DataRelation dr;
private DataView DV_faqs;
private void loadXML_faqs()
{
try
{
//load xml data
xmlPath = Server.MapPath("~/FAQs.xml");
DS_faqs.ReadXml(xmlPath);
//table names
/*
* DS_faqs.tables[1] = "question"
* DS_faqs.tables[2] = "answer"
* */
// create data columns
parentDC = DS_faqs.Tables[1].Columns[0];
childDC = DS_faqs.Tables[2].Columns[0];
//set sessions for grid_dataBound
Session["ds"] = DS_faqs;
//create data relation
dr = new DataRelation("my_dr", parentDC, childDC, false);
//add data relation
DS_faqs.Relations.Add(dr);
//create dataview
DV_faqs = ((DataTable)DS_faqs.Tables[1]).DefaultView;
//bind to grid
this.gridFAQs.DataSource = DV_faqs;
this.gridFAQs.DataBind();
}
catch (Exception ex)
{
throw ex;
}
}
The HierarGrid is coded as follows; by setting the TemplateFileName of the even to the name of the user control.
public void gridFAQs_templateSelection(object sender, HierarGridTemplateSelectionEventArgs e)
{
e.TemplateFilename = "FAQ_item.ascx";
}
FAQ_item.ascx
This user control represents a single answer item that will be shown when a grid is collapsed. In our just, just some plain formatted text.

The user-control just has a single label control with few formatting.
<%@ Control
Language="C#"
AutoEventWireup="true"
...
%>
<br />
<div style="margin-left:10px; margin-right:5px;">
<asp:Label
ForeColor="#8C4510"
Font-Names="Arial"
Font-Size="XX-Small"
ID="lbl_answer"
runat="server"
/>
</div>
<br />
Coding it would be hooking up the binding event to the Init page event:
protected override void OnInit(EventArgs e)
{
this.DataBinding += new EventHandler(bindingEvent);
base.OnInit(e);
}
The next section is the event handler that manipulates the label control.
protected void bindingEvent(object sender, EventArgs e)
{
DataSet myDS = (DataSet)((DataGridItem)this.BindingContainer).DataItem;
string answerString = myDS.Tables[2].Rows[0][1].ToString();
//apply formatting selection
answerString = answerString.Replace("[break_here]", "<br />");
answerString = answerString.Replace("[bold]", "<strong>");
answerString = answerString.Replace("[end_bold]", "</strong>");
answerString = answerString.Replace("[italic]", "<i>");
answerString = answerString.Replace("[end_italic]", "</i>");
//set the label
this.lbl_answer.Text = answerString;
}
This is where the user defined custom tags get replaced by the standard html tags during rendering.