Link to home
Start Free TrialLog in
Avatar of jumpstart0321
jumpstart0321

asked on

ASP.net Expandable panel.

Ok, it sounds easy enough; but for some reason I can't find anything. What I'm looking for is some sort of panel type thing that appears like the following:
+Click here for options
[when + is clicked, I want it to expand]
[Buttons, textboxes, etc in expanded menu]
I'm using vs 2008. Anybody have any idea of which control to use?
Avatar of aibusinesssolutions
aibusinesssolutions
Flag of United States of America image

It depends on how fancy you want to get with it.

http://www.asp.net/AJAX/AjaxControlToolkit/Samples/CollapsiblePanel/CollapsiblePanel.aspx

You could also just create a div layer that shows or hides with CSS and javascript for a simple approach.
Hi There,

There are all sort of ways to do this. I would use a javascript framework. Have a look here (http://jqueryui.com/demos/), it's easy to implement and you don't have all the cumbersome code in your page like you do when you use the Microsoft ajax controls.

Sean
ASKER CERTIFIED SOLUTION
Avatar of bedanand
bedanand
Flag of Nepal image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of karakav
karakav

Here is another collapsible panel that doesn't need ajax. Personally, I prefer this one as it is more cutomizable. You just have to add the class in a class library project, build the project and then reference the dll in you web application project. You can change everything if you want. I attached a snippet.

P.S.: In the Panel project, you have to manually include the references : System.Drawing and System.Web

If you prefer to use it as is, just change the extension of the file I attach from .txt to .dll and then include it in your project.

Hope it helps.
***********The panel class ********************
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Text;
using System.Collections.Specialized;
using System;
using System.Web;
 
namespace CollapsiblePanel
{
	#region Panel Control (Expandable)
	[ToolboxData("<{0}:Panel runat=server Expandable='true' Width='200px'></{0}:Panel>")]
	public class Panel :System.Web.UI.WebControls.Panel,IPostBackDataHandler
	{
		public Panel()
			: base()
		{
			Expandable = true;
			RenderInBox = false;
			Title = "Panel";
			Font.Name = "verdana";
			Font.Size = FontUnit.Point(10);
			Margin = 2;
			Closed = false;
			ToggleButton = null;
			CaptionDithered = false;
			RightToLeft = false;
			ForeColor = Color.Black;
			BorderColor = Color.AliceBlue;
			ClickButtonColor = ForeColor;
		}
 
		// Automatically updates the Closed property based on the content
		// of hidden field named as this control
		public virtual bool LoadPostData(string postDataKey,NameValueCollection postCollection)
		{
			bool currentValueOfClosed = Closed;
			bool postedValueOfClosed = Convert.ToBoolean(postCollection[postDataKey]);
 
			// In case where the field would be empty?
			if (!currentValueOfClosed.Equals(postedValueOfClosed))
			{
				Closed = postedValueOfClosed;
				return true;
			}
 
			return false;
		}
		public virtual void RaisePostDataChangedEvent()
		{
		}
		// Fires when the panel gets loaded
		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);
 
			// Check the browser capabilities and disable collapse/expand if needed
			bool uplevel = false;
			HttpBrowserCapabilities caps = Page.Request.Browser;
			if (caps.Browser.ToUpper().IndexOf("IE") > -1)
			{
				// This is IE. But is it at least v5?
				if (caps.MajorVersion > 4)
					uplevel = true;
			}
 
			// If the browser is not IE5 or higher, drop collapse/expand 
			if (!uplevel)
			{
				Expandable = false;
				RenderInBox = true;
			}
		}
		// Gets the name of the hidden field used to carry client info
		private string HiddenFieldName
		{
			get
			{
				return ID;
			}
		}
		// Makes the control expandable on demand
		public bool Expandable
		{
			get
			{
				return Convert.ToBoolean(ViewState["Expandable"]);
			}
			set
			{
				ViewState["Expandable"] = value;
			}
		}
		// Render the contents of the in a box 
		// (used only if Expandable is false)
		public bool RenderInBox
		{
			get
			{
				return Convert.ToBoolean(ViewState["RenderInBox"]);
			}
			set
			{
				ViewState["RenderInBox"] = value;
			}
		}
		// Whether the contents of the expandable panel must be visible
		public bool Closed
		{
			get
			{
				return Convert.ToBoolean(ViewState["Closed"]);
			}
			set
			{
				ViewState["Closed"] = value;
			}
		}
		// The text displayed as the caption of the expandable panel
		public string Title
		{
			get
			{
				return Convert.ToString(ViewState["Title"]);
			}
			set
			{
				ViewState["Title"] = value;
			}
		}
		// The margin to use if the panel is expandable
		public int Margin
		{
			get
			{
				return Convert.ToInt32(ViewState["Margin"]);
			}
			set
			{
				ViewState["Margin"] = value;
			}
		}
		// The background of the caption is hor. dithered
		public bool CaptionDithered
		{
			get
			{
				return Convert.ToBoolean(ViewState["CaptionDithered"]);
			}
			set
			{
				ViewState["CaptionDithered"] = value;
			}
		}
		// Indicates the direction of the dithering
		public bool RightToLeft
		{
			get
			{
				return Convert.ToBoolean(ViewState["RightToLeft"]);
			}
			set
			{
				ViewState["RightToLeft"] = value;
			}
		}
		// Indicates the color of the click button to expand/collapse
		public Color ClickButtonColor
		{
			get
			{
				return (Color)ViewState["ClickButtonColor"];
			}
			set
			{
				ViewState["ClickButtonColor"] = value;
			}
		}
		// Render the control
		protected override void Render(HtmlTextWriter output)
		{
			if (!Expandable)
			{
				if (!RenderInBox)
					base.Render(output);
				else
					RenderContentsInBox(output);
				return;
			}
 
			// Add margin information if the panel is expandable
			Style["margin"] = Margin.ToString();
			Style["display"] = (Closed ? "none" : "");
			string originalID = this.UniqueID;
			ID = this.UniqueID + "_theDiv";
 
			// The internal panel must cover 100% of the parent area
			// irrespective of the physical width. 
			Unit oldWidth = Width;
			Width = Unit.Percentage(100);
 
			// Register the hidden field to communicate
			Page.ClientScript.RegisterHiddenField(originalID,Closed.ToString());
 
			// Capture the default output of the Panel
			StringWriter writer = new StringWriter();
			HtmlTextWriter buffer = new HtmlTextWriter(writer);
			base.Render(buffer);
			string panelOutput = writer.ToString();
 
			// Restore the wanted width
			Width = oldWidth;
			BuildControlTree(output,originalID,panelOutput);
			return;
		}
		// Handle the PreRender event
		protected LiteralControl ToggleButton;
		protected override void OnPreRender(EventArgs e)
		{
			base.OnPreRender(e);
 
			if (Expandable)
				ToggleButton = CreateClientButton();
		}
		// Build the markup for this custom Panel control
		private void BuildControlTree(HtmlTextWriter output,string id,string panelOutput)
		{
			Table t = new Table();
			t.ID = id + "_thePanel";
			t.CellPadding = 0;
			t.CellSpacing = 0;
			t.BorderColor = BorderColor;
			t.BorderStyle = BorderStyle.Outset;
			t.BorderWidth = Unit.Pixel(1);
			t.ForeColor = ForeColor;
			t.Font.Name = Font.Name;
			t.Font.Size = Font.Size;
			t.Width = Width;
			if (CaptionDithered)
			{
				string filterString = "progid:DXImageTransform.Microsoft.Gradient(gradienttype=1,startColorstr='{0}',endColorstr='{1}'";
				if (RightToLeft)
					t.Style["filter"] = String.Format(filterString,
						Color.Snow.Name,
						BorderColor.Name);
				else
					t.Style["filter"] = String.Format(filterString,
						BorderColor.Name,
						Color.Snow.Name);
			}
 
			// Prepare the topmost row
			TableRow rowTop = new TableRow();
			if (!CaptionDithered)
				rowTop.BackColor = t.BorderColor;
 
			// Leftmost cell: title
			TableCell cellTop = new TableCell();
			cellTop.Text = String.Format("<b>&nbsp;{0}</b>",Title);
			cellTop.HorizontalAlign = HorizontalAlign.Left;
			rowTop.Cells.Add(cellTop);
 
			// Rightmost cell: expand/collapse button
			TableCell cellTopRight = new TableCell();
			cellTopRight.HorizontalAlign = HorizontalAlign.Right;
			LiteralControl imgRight = ToggleButton;
			if (imgRight != null)
				cellTopRight.Controls.Add(imgRight);
			rowTop.Cells.Add(cellTopRight);
 
			// Add the top row to the table
			t.Rows.Add(rowTop);
 
			// Insert the Panel's markup in the table cell 
			TableRow rowBody = new TableRow();
			TableCell cellBody = new TableCell();
			cellBody.BackColor = Color.White;
			cellBody.ColumnSpan = 2;
			cellBody.Text = panelOutput;
 
			rowBody.Cells.Add(cellBody);
			t.Rows.Add(rowBody);
 
			// Output
			t.RenderControl(output);
		}
		// Add a client-side DHTML button
		private LiteralControl CreateClientButton()
		{
			string scriptFuncName = "Toggle" + this.UniqueID;
			string scriptName = "__TogglePanel" + this.UniqueID;
			string html = "<a href='javascript:{0}()'><span style='color:{1};font-family:webdings;text-decoration=none;font-weight=700;'>2</span></a>&nbsp;";
			html = String.Format(html,
				scriptFuncName,
				ClickButtonColor.Name);
 
			LiteralControl lit = new LiteralControl(html);
 
			string stateVar = "closed_" + this.UniqueID;
			string ctlVar = this.UniqueID + "_theDiv";
 
			// Get the name of the Form
			string formName = "Form1";
			foreach (Control ctl in Page.Controls)
			{
				if (ctl is HtmlForm)
					formName = ctl.ID;
			}
 
			StringBuilder sb = new StringBuilder("<script language=Javascript>\n");
			sb.Append("function ");
			sb.Append(scriptFuncName);
			sb.Append("() {\n");
			string hiddenFieldExpr = "document.forms[\"" + formName + "\"][\"" + UniqueID + "\"].value";
			sb.Append("var " + stateVar + " = " + hiddenFieldExpr + ";");
			sb.Append("if (" + stateVar + ".toLowerCase()==\"true\") {\n");
			sb.Append(ctlVar);
			sb.Append(".style[\"display\"] = \"\";");
			sb.Append(hiddenFieldExpr + "=false;}");
			sb.Append("\nelse {\n");
			sb.Append(ctlVar);
			sb.Append(".style[\"display\"] = \"none\"; " + hiddenFieldExpr + "=true;}");
			sb.Append("\n}\n<");
			sb.Append("/");
			sb.Append("script>");
 
			if (!Page.ClientScript.IsClientScriptBlockRegistered(scriptName))
				Page.ClientScript.RegisterClientScriptBlock(typeof(String),scriptName,sb.ToString());
 
			return lit;
		}
		// Render the panel in a box
		private void RenderContentsInBox(HtmlTextWriter output)
		{
			Style["border-left"] = String.Format("{0} solid {1}",BorderWidth,BackColor.Name);
			Style["border-right"] = String.Format("{0} solid {1}",BorderWidth,BackColor.Name);
			Style["border-top"] = String.Format("3px solid {0}",BorderColor.Name);
			Style["border-bottom"] = String.Format("3px solid {0}",BorderColor.Name);
			Style["padding"] = Margin.ToString();
 
			base.Render(output);
		}
	}
	#endregion
}
 
 
*********** The aspx file *****************
 
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="ColPanel.aspx.vb" Inherits="ColPanel" %>
 
<%@ Register Namespace="CollapsiblePanel" Assembly="CollapsiblePanel" TagPrefix="col" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <col:Panel ID="ClosedPanel" runat="server" Closed="true" Width="80%">
                <asp:Label ID="lblName" runat="server" Text="Enter your first name here:"  ForeColor="blue"/>
                <asp:TextBox ID="txtName" runat="server" />
            </col:Panel>
            <col:Panel ID="OpenPanel" runat="server" Closed="false" Width="90%">
                <asp:Label ID="Label1" runat="server" Text="Enter your last name here:"  ForeColor="blue"/>
                <asp:TextBox ID="TextBox1" runat="server" />
            </col:Panel>            
        </div>
    </form>
</body>
</html>

Open in new window

CollapsiblePanel.txt
Follow aibusinesssolutions's solution. Ive used this many times, and it works well enough for me!

I am actually currently using it in one of my applications now