Hierarchical Gridview

23 09 2008

After using many professional/commercial controls, I was often disappointed in using them. When you are following the simple sample path, it will work. But if you really want to customize the control, the percent rate of bugs and unwanted states increase. If a control cannot be reliable, it’s better to do it and keep a full control on the source code.

That’s why, rather than spending some money to own your multi-gridview and waiting each day after a patch, here is a cool tip to adapt a standard Gridview in hierarchical Gridview:

Create a standard GridView on a webform and create a template field column at the end of the columns collection. Add in the template item : “<tr><td> Second Row </td></tr>”.

That all folk ! When addind this code, the DOM structure of the gridview is broken(Yes, it’s not W3C). But the result is there. Working with IE,Firefox and Chrome.

If we analyse in deep the generating HTML Code of the gridview, we can see the following structure:

<table>

<tr><th>col1</th><th>col second row</th></tr>

<tr><td>col1 value</td><td>

<tr><td>Second Row</td></tr>

</td></tr>

</table>

When adding TR in td(cell of gridview), a new row is created. However, we can manage the visibility of this new row through cell properties. Thus, with an appropriate extender(link,image,other control), we can hide or show the row.

I have created for my personal purpose 2 definition of template Field Column that I can add to a gridview and render it like a Hierarchical Gridview.

Here the code:

 /// <summary>

    /// Build a sub row for each row.

    /// </summary>

    [ToolboxData(@”<{0}:SubRowBoundField></{0}:SubRowBoundField>”)]

    public class SubRowBoundField : TemplateField

    {

        public TextBox ExpandedRowsState

        {

            get;

            set;

        }

 

        public SubRowBoundField()

            : base()

        {

            LeftPadding = new Unit(“20px”);

            TextBox txt = new TextBox();

            txt.ID = “_ExpandedRowsState”;

            ExpandedRowsState = txt;

        }

 

        /// <summary>

        /// Space at the left of the cell (default:20px)

        /// </summary>

        public Unit LeftPadding { get; set; }

 

        public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)

        {

            base.InitializeCell(cell, cellType, rowState, rowIndex);

            string expandedRowStateValue = (HttpContext.Current.Request.Form[ExpandedRowsState.UniqueID] != null) ? HttpContext.Current.Request.Form[ExpandedRowsState.UniqueID] : ExpandedRowsState.Text;

            if (cellType == DataControlCellType.Header)

            {

                //cell.Controls.Clear();

                //we store the expanded row collection in an hidden field

                ExpandedRowsState.Style.Add(“display”, “none”);

                cell.Controls.Add(ExpandedRowsState);

                //cell.Text = string.Empty;

                cell.Style.Add(“width”, “100px”);

                cell.Style.Add(“display”, “none”);

 

            }

            else if (cellType == DataControlCellType.DataCell)

            {

                GridView g = this.Control as GridView;

                cell.Style.Add(“display”, “none”);

 

                bool displayPlus = (expandedRowStateValue.IndexOf(“[“ + g.PageIndex + “,” + rowIndex + “]”) > -1) ? false : true;

 

                cell.Controls.AddAt(0, new LiteralControl(

                    @”<tr>

                        <td colspan=””100%”” style=””padding-left:” + LeftPadding.ToString() + @”””>

                            <div id=” + g.ClientID + @”_div” + rowIndex + @” 

                                style=””display:” + ((displayPlus)?“none”:“block”) + @”;OVERFLOW: auto;WIDTH:100%”” >”));

                cell.Controls.Add(new LiteralControl(cell.Text));

                cell.Controls.Add(new LiteralControl(@”</div></td></tr>”));

 

            }

        }

    }

 

    /// <summary>

    /// Build a sub row expand-collapse action for each row.

    /// </summary>

    [ToolboxData(@”<{0}:SubRowExtendBoundField></{0}:SubRowExtendBoundField>”)]

    public class SubRowExtendBoundField : TemplateField

    {

        public string CssClassPlus { get; set; }

        public string CssClassMinus { get; set; }

        public TextBox ExpandedRowsState { get; set; }

 

        public SubRowExtendBoundField()

            : base()

        {

            TextBox txt = new TextBox();

            txt.ID = “_ExpandedRowsStateExpander”;

            ExpandedRowsState = txt;

        }

 

        public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)

        {

            base.InitializeCell(cell, cellType, rowState, rowIndex);

            string expandedRowStateValue = (HttpContext.Current.Request.Form[ExpandedRowsState.UniqueID] != null) ? HttpContext.Current.Request.Form[ExpandedRowsState.UniqueID] : ExpandedRowsState.Text;

            if (cellType == DataControlCellType.Header)

            {

                //we store the expanded row collection in an hidden field

                ExpandedRowsState.Style.Add(“display”, “none”);

                cell.Controls.Add(ExpandedRowsState);

            }

            else if (cellType == DataControlCellType.DataCell)

            {

                GridView g = this.Control as GridView;

                TextBox txtExpanded = g.HeaderRow.Cells[g.Columns.Count – 1].Controls[0] as TextBox;

                string sExpand = @”

                    document.getElementById(‘” + g.ClientID + @”_btnPlus” + rowIndex + @”‘).style.display=’none’;

                    document.getElementById(‘” + g.ClientID + @”_btnMinus” + rowIndex + @”‘).style.display=’block’;

                    document.getElementById(‘” + g.ClientID + @”_div” + rowIndex + @”‘).style.display=’block’;

                    document.getElementById(‘” + ExpandedRowsState.ClientID + @”‘).value=document.getElementById(‘” + ExpandedRowsState.ClientID + @”‘).value+'[“+g.PageIndex+“,” + rowIndex + @”]’;

                    document.getElementById(‘” + txtExpanded.ClientID + @”‘).value=document.getElementById(‘” + txtExpanded.ClientID + @”‘).value+'[“ + g.PageIndex + “,” + rowIndex + @”]’;”;

                string sCollapse = @”

                    document.getElementById(‘” + g.ClientID + @”_btnPlus” + rowIndex + @”‘).style.display=’block’;

                    document.getElementById(‘” + g.ClientID + @”_btnMinus” + rowIndex + @”‘).style.display=’none’;

                    document.getElementById(‘” + g.ClientID + @”_div” + rowIndex + @”‘).style.display=’none’;

                    document.getElementById(‘” + ExpandedRowsState.ClientID + @”‘).value=document.getElementById(‘” + ExpandedRowsState.ClientID + @”‘).value.replace(‘[“ + g.PageIndex + “,” + rowIndex + @”]’,”);

                    document.getElementById(‘” + txtExpanded.ClientID + @”‘).value=document.getElementById(‘” + txtExpanded.ClientID + @”‘).value.replace(‘[“ + g.PageIndex + “,” + rowIndex + @”]’,”);”;

 

                string cancelBubble = @”window.event.cancelBubble=true;window.event.returnValue=false;”;

                sExpand += cancelBubble;

                sCollapse += cancelBubble;

 

 

                bool displayPlus = (expandedRowStateValue.IndexOf(“[“ + g.PageIndex + “,” + rowIndex + “]”) > -1) ? false : true;

 

                LiteralControl lcPlus = new LiteralControl(

                    @”<div id='” + g.ClientID + @”_btnPlus” + rowIndex + @”‘ style=””display:” + ((displayPlus) ? “block” : “none”) + @””” class=” + CssClassPlus + @”

                    onclick=””javascript:” + sExpand + @”””></div>”);

                cell.Controls.Add(lcPlus);

 

                LiteralControl lcMinus = new LiteralControl(

                    @”<div id='” + g.ClientID + @”_btnMinus” + rowIndex + @”‘ style=””display:” + ((!displayPlus) ? “block” : “none”) + @””” class=” + CssClassMinus + @”

                    onclick=””javascript:” + sCollapse + @”””></div>”);

                cell.Controls.Add(lcMinus);

            }

 

        }

 

    }

Advertisements