Click here to Skip to main content
15,885,366 members
Articles / Web Development / ASP.NET

Creating a DataGrid that expands and collapses like a tree control

Rate me:
Please Sign up or sign in to vote.
4.56/5 (10 votes)
10 Apr 2006CPOL3 min read 74.5K   1.4K   43  
A Custom DataGrid Paging Techniuque
using System;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Collections;
using System.Data;
using System.Drawing;
using System.Web.UI;

 

namespace TreeGridDemo
{
	/// <summary>
	/// Manages Grid Binding For Reserving Last client state of the control
	/// And Also manages rendering client side controls and scripts
	/// </summary>
	public class TreeGridUIManager
	{

		private  ArrayList	gridsToManage=new ArrayList();
		/// <summary>
		/// Adds a new grid so that it can be converted into  treegrid
		/// </summary>
		/// <param name="treeGridToManage"></param>
		/// <param name="numItemsPerPage"></param>
		public  void AddGridToManage(DataGrid treeGridToManage,int numItemsPerPage)
		{	
			treeGridToManage.Attributes.Add("NumItemsPPage",numItemsPerPage.ToString());
			AddTemplateColumn(treeGridToManage);
			gridsToManage.Add(treeGridToManage);
		}

	
		/// <summary>
		/// Is Called instead of [gridName].DataBind To Bind the grid
		/// with resering its last client state
		/// </summary>
		public void DataBind()
		{
			string  script =TreeGridScriptRenderer.GetScript(gridsToManage);
			if(gridsToManage.Count>0)
			{	
				((DataGrid)gridsToManage[0]).Page.RegisterClientScriptBlock("TREEGRIDSCRIPT",script);
			}
			foreach(DataGrid treeGridToManage in gridsToManage)
			{
				treeGridToManage.PreRender+=new EventHandler(treeGridToManage_PreRender);

				ArrayList stateList=new ArrayList();
				for(int i=0;i<treeGridToManage.Items.Count;i++)
				{
					HtmlInputHidden hiddenTreeGridState=(HtmlInputHidden)treeGridToManage.Items[i].Cells[0].FindControl("hiddenShowHideStatus\n");
					if(hiddenTreeGridState!=null)
					{
						stateList.Add(hiddenTreeGridState.Value);
					}	
				}

				treeGridToManage.DataBind();
				
				if(stateList.Count>0)
				{
					for(int i=0;i<stateList.Count;i++)
					{
						HtmlInputHidden hiddenTreeGridState=(HtmlInputHidden)treeGridToManage.Items[i].Cells[0].FindControl("hiddenShowHideStatus\n");
						if(hiddenTreeGridState!=null)
						{
							hiddenTreeGridState.Value=stateList[i].ToString();
						}
					}
				}
			}
		}

		private  void treeGridToManage_PreRender(object sender, EventArgs e)
		{
			PopulateGridSeparators((DataGrid)sender);
		}

		/// <summary>
		/// Renders The Expand Collapse Butons
		/// </summary>
		/// <param name="treeGridToManage"></param>
		private  void PopulateGridSeparators(DataGrid treeGridToManage)
		{
			int pagerCellColSpan=0;
			int numItemsPPage=int.Parse(treeGridToManage.Attributes["NumItemsPPage"]);
			if(treeGridToManage.Items.Count>0)
			{
				pagerCellColSpan=treeGridToManage.Items[0].Cells.Count;

				int numSeparatorsCreated=0;
				for(int index=1;index<treeGridToManage.Items.Count+numSeparatorsCreated;index+=(numItemsPPage+1),numSeparatorsCreated++)
				{
					string clientText="";
					clientText+="<INPUT TYPE =BUTTON ID=BTN"+index+" ";
					clientText+="VALUE=\"-\" ";
					clientText+="ONCLICK=\"javascript:ExpandCollapse(this,'"+treeGridToManage.ClientID+"',"+index+","+numItemsPPage+")\" ";
					clientText+="STYLE=\"BORDER-RIGHT: gray thin solid; BORDER-TOP: gray thin solid; BORDER-LEFT: gray thin solid; WIDTH: 25px; BORDER-BOTTOM: gray thin solid; HEIGHT: 28px\"";
				
					clientText+=">";

					TableCell cell=new TableCell();
					cell.Text=clientText;
					cell.Width=30;
					cell.BorderStyle=BorderStyle.Dotted;
					TableCell cell2=new TableCell();
					cell2.ColumnSpan=pagerCellColSpan;
					cell2.HorizontalAlign=HorizontalAlign.Center;
					cell2.Text="From "+(index-numSeparatorsCreated)+" To "+(((index-numSeparatorsCreated)+numItemsPPage-1));
					cell2.BorderStyle=BorderStyle.Dotted;
					DataGridItem item=new DataGridItem(0,0,ListItemType.Separator);
					item.BackColor=Color.LightGray;
					item.Cells.Add(cell);
					item.Cells.Add(cell2);

					treeGridToManage.Controls[0].Controls.AddAt(index,item);
				}
			}
			
		}


		public  void AddTemplateColumn(DataGrid dg)
		{
			TemplateColumn tc1 = new TemplateColumn();
			tc1.ItemTemplate = new DataGridTemplate(ListItemType.Item, "Column1\n");
			dg.Columns.AddAt(0,tc1);

		}

	}


	/// <summary>
	/// This is for Adding a template column to the grid
	/// that contains the hidden fields responsible for
	/// grid state preservation
	/// </summary>
	class DataGridTemplate : System.Web.UI.ITemplate
	{
		ListItemType templateType;
		string columnName;
		public DataGridTemplate(ListItemType type, string colname)
		{
			templateType	= type;
			columnName		= colname;
		}
		public void InstantiateIn(System.Web.UI.Control container)
		{
			// The Hidden Field Built Dynamically
			HtmlInputHidden hiddenShowHideStatus=new HtmlInputHidden();
			hiddenShowHideStatus.Value="none";
			hiddenShowHideStatus.ID="hiddenShowHideStatus";
			
			switch(templateType)
			{
				case ListItemType.Item:
				case ListItemType.EditItem:
						container.Controls.Add(hiddenShowHideStatus);
						break;
			}
		}
	}


	/// <summary>
	/// Dynamically builds the client script according
	/// to the grids on the page   
	/// </summary>
	class TreeGridScriptRenderer
	{
		public static  string GetScript(ArrayList gridsToManage)
		{
			string gridClientIDsArray="grids=new Array(";
			for(int i=0;i<gridsToManage.Count;i++)
			{
				string gridClientID=((DataGrid)gridsToManage[i]).ClientID;
				gridClientIDsArray+="'"+gridClientID+"',";
			}
			gridClientIDsArray=gridClientIDsArray.Remove(gridClientIDsArray.LastIndexOf(","),1);
			gridClientIDsArray+=");";


			System.Text.StringBuilder sb=new System.Text.StringBuilder();
			sb.Append("\n<SCRIPT Language=javascript>\n");
			sb.Append("//************************************** ABOUT TREEGRID **************************************************\n");
			sb.Append("// AUTHOR:Ahmed Abdelgawad email:[ahmad_abdelgawad@yahoo.com],[agawad@gmail.com]\n");
			sb.Append("// DATE CREATED:	19/3/2003\n");
			sb.Append("//********************************************************************************************************\n");
				
			sb.Append("	//********************************************************************************************************\n");
			sb.Append("	//CALLED EVERY TIME YOU COLLAPSE OR EXPAND THE GRID ITEMS\n");
			sb.Append("	//********************************************************************************************************\n");
			sb.Append("		function ExpandCollapse(sender,gridClientID,rowIndex,numItemsPerPage)\n");
			sb.Append("		{\n");
			sb.Append("			var grid=document.getElementById(gridClientID);\n");
			sb.Append("			for(i=rowIndex+1;i<(rowIndex+numItemsPerPage+1);i++)\n");
			sb.Append("			{\n");
			sb.Append("				try\n");
			sb.Append("				{\n");
			sb.Append("					//SHOW OR HIDE THE ROW ACCORDING TO CURRENT STATE\n");
			sb.Append("					grid.rows[i].style.display=sender.value=='-'?'none':'block';\n");
				
			sb.Append("					//SET THE HIDDEN VALUE FOR SERVER SIDE STATE PRSERVATION\n");
			sb.Append("					hiddenShowHideStatus=grid.rows[i].cells[0].children[0];\n");
			sb.Append("					if(hiddenShowHideStatus&&hiddenShowHideStatus.type=='hidden')\n");
			sb.Append("					{\n");
			sb.Append("						hiddenShowHideStatus.value=sender.value=='-'?'none':'block';\n");
			sb.Append("					}\n");
			sb.Append("				}\n");
			sb.Append("				catch(ex)\n");
			sb.Append("				{\n");
			sb.Append("					break;\n");
			sb.Append("				}\n");
			sb.Append("			}\n");
			sb.Append("			//CONVERT THE TEXT OF THE BUTTON CONTROL FROM + TO - AND VICE VERSA\n");
			sb.Append("			sender.value=(sender.value=='-')?'+':'-';\n");
			sb.Append("		}\n");
			sb.Append("		//********************************************************************************************************\n");
			sb.Append("		//CALLED ON PAGE LOAD FOR CLIENT STATE PRESERVATION    SetTreeGridStatus()\n");
			sb.Append("		//********************************************************************************************************\n");
			sb.Append("		this.onload=function()\n");
			sb.Append("		{\n");
			sb.Append("				"+gridClientIDsArray+"\n");
			sb.Append("				for(j=0;j<grids.length;j++) \n");
			sb.Append("				{\n");
			sb.Append("					var grid=document.getElementById(grids[j]); \n");			
			sb.Append("					if(grid) \n");
			sb.Append("					{ \n");
			sb.Append("						for(i=0;i<grid.rows.length;i++)\n");
			sb.Append("						{\n");
			sb.Append("							hiddenShowHideStatus=grid.rows[i].cells[0].children[0];\n");
			sb.Append("							if(hiddenShowHideStatus)\n");
			sb.Append("							{\n");
			sb.Append("								if(hiddenShowHideStatus.type=='hidden')\n");
			sb.Append("								{\n");
			sb.Append("									grid.rows[i].style.display=hiddenShowHideStatus.value=='none'?'none':'block';\n");
			sb.Append("								}\n");
			sb.Append("							}\n");
			sb.Append("						}\n");
			sb.Append("						SetButtonState(grid);\n");
			sb.Append("					}\n");
			sb.Append("				}\n");
			sb.Append("		};\n");
			sb.Append("		//********************************************************************************************************\n");
			sb.Append("		// CALLED AFTER [SetTreeGridStatus()] TO MANAGE BUTTON TEXT\n");
			sb.Append("		// CHECK FOR THE NEXT ROW IF SHOWING THEN TEXT='-' ELSE '+'\n");
			sb.Append("		//********************************************************************************************************\n");
			sb.Append("		function SetButtonState(grid)\n");
			sb.Append("		{\n");
			sb.Append("			//var grid=document.getElementById('DataGrid1');\n");
			sb.Append("			for(i=0;i<grid.rows.length;i++)\n");
			sb.Append("			{\n");
			sb.Append("				btnCtrl=grid.rows[i].cells[0].children[0];\n");
			sb.Append("				if(btnCtrl)\n");
			sb.Append("				{\n");
			sb.Append("					if(btnCtrl.type=='button')\n");
			sb.Append("					{\n");
			sb.Append("						subRow=grid.rows[i+1];\n");
			sb.Append("						if(subRow)\n");
			sb.Append("						{\n");
			sb.Append("							btnCtrl.value=subRow.style.display=='none'?'+':'-';	\n");
			sb.Append("						}\n");
			sb.Append("					}\n");
			sb.Append("				}\n");
			sb.Append("			}\n");
			sb.Append("		}\n");
			sb.Append("	//**********************************************************************************************************\n");
			sb.Append("</SCRIPT>");
			return sb.ToString();
		}
	}


	

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Web Developer
Kuwait Kuwait
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions