Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Creating Postback Rows in a GridView

5.00/5 (1 vote)
22 Mar 2011CPOL2 min read 10.8K  
Code for creating postback rows in a GridView
This post describes creation of an ASP.NET control for creating collapsible nodes within GridViews, incorporating JavaScript for expanding and collapsing child nodes, and implementing custom event handling for node selection.

Introduction

I recently started to create an ASP.NET control that had collapsible nodes. The GridViews made a visual tree looking control based on the parent to child business object.

For example, a main node would expand to show a sub-main node and then the sub-main node would have element nodes.

All of these controls had GridViews that contained JavaScript to expand or collapse the child nodes. There were several ways that I found on the net to hook into the postback of the controls.

The code contains the main Node that I used for creating a collapse image background with the name of the node and then another GridView control called MainTreeNode that I set the datasource and bind to during the OnRowDataBound event of the GridView.

ASP.NET
<table style="border:solid 1px gray; height:390px;">
<tr>
<td valign="top">
<asp:GridView ID="MainGridview" runat="server"
AutoGenerateColumns="false"
CellPadding="0"
CellSpacing="0"
GridLines="None"
ShowFooter="false"
ShowHeader="false"
OnRowDataBound="MainGridview_OnRowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<table>
<tr>
<td>
<a href="javascript:ExpandCollapse('div<%# DataBinder.Eval(
  Container.DataItem, "ID")%>', 'selector<%# DataBinder.Eval(
  Container.DataItem, "ID")%>');">
<div id="selector<%# DataBinder.Eval(Container.DataItem, "ID")%>"
class="expandBar">

I am able to FindControl to get the MainTreeNode and then set the datasource to the DataItem’s property array.

The main question at this point is how to get an OnClick event to fire from the MainTreeNode. Note the OnNodeSelectedEvent="MainTreeNode_OnNodeSelected" of the child.

This node event was achieved by creating a control event and having the IPostBackEventHandler interface implemented on the node.

C#
public partial class MainTreeNode: GrideView, IPostBackEventHandler
{
  // The AllowPostBack is a bool that will allow
  // the control to add or not the post back event.
  public bool AllowPostBack { get; set; }

  protected override void OnRowDataBound(GridViewRowEventArgs e){
    base.OnRowDataBound(e);
    if(e.Row.DataItem != null && AllowPostBack){
      string arg = string.Format("argument_{0}", e.Row.RowIndex);
      e.Row.Attributes.Add("onclick", 
            Page.ClientScript.GetPostBackEventReference(this, arg));
    }
  }

  protected override void PrepareControlHierarchy(){
    base.PrepareControlHierarchy();
  }

  protected override void RaisePostBackEvent(string eventArgument){
    base.RaisePostBackEvent(eventArgument);
  }
}

Simplistic of course, but as noted above, there are several areas of the control that can be utilized. This would be the basic functionality of causing a postback on the clicking of the node (GridRow).

The next item to make sure the control has handled is the custom event handler in the MainTreeNode class:

C#
protected override void RaisePostbackEvent(string argument){
  if (argument != null){
    // provide functionality to perform the post back.
    // Create event args to pass to the OnNodeSelected event.
    NodeSelectedEventArg e = new NodeSelectedEventArg();
    OnNodeSelected(e);
  }
}

private static readonly object NodeSelectedEventKey = new object();

public event EventHandler<nodeselectedeventarg> NodeSelectedEvent{
  add { Events.AddHandler(NodeSelectedEventKey, value); }
  remove { Events.RemoveHandler(NodeSelectedEventKey, value); }
}

protected virtual void OnNodeSelected(NodeSelectedEventArg e){
  base.RaiseEvent(NodeSelectedEventKey, e);
}

protected virtual void NodeSelected(object DataItem){
  NodeSelectedEventArg e = new NodeSelectedEventArg();
  e.dataItem = DataItem;
  OnNodeSelected(e);
}

The event is now hooked into the control’s Events collection and can be used if the containing control subscribes to the event. A delegate could also work here as well.

Now the code is provided as the building block foundation, more details will depend on the work that needs to be accomplished by the event. The event argument class can be created to handle any data item that needs to be persistent between controls, and I have found it very useful to keep the data item intact through custom event arguments.

My previous post had taken the original postback requirement into account, but as provided in the above code, moving the GetPostBackEventReference method into OnRowDataBound gives the option to have the GridView.Row.DataItem available for keeping track of any data in the data item for the postback.

Hopefully, this will clear up any questions on the previous posting. I have worked with this control for a bit, and I am very pleased with how the GridView reacted to the upgrade… :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)