Creating a collapsable area in ASP.NET
currently i've built a collapseControl which behaves similar to a label (associatedControlID) to control the collapse-state of a control.
following control i'd like to build:
collapsableArea http://img692.imageshack.us/img692/3307/stackoverflowcollapseab.jpg
i thought of something like:
put my already build collapsableControl and some other control (eg. panel) together to get a collapsableArea.first try:
i tried to extend a panel and did the following:this.Parent.Controls.Add(collapsableControl);
but this gave me: "not correct life cycle step", "can't modify", "nullReference", ... exceptions
so i gave it another try (which i believe the better choice, due to getting no tagKey):
i extended a placeholder and did the following:this.Controls.Add(collapsableControl);
this.Controls.Add(coll开发者_JS百科apsablePanel);
this caused other problems, like: i only want to set the text of the panel, the style of the panel, ...
wired!
do you have any solutions for this scenario?
edit:
i came up with another solution: another solution http://img109.imageshack.us/img109/3307/stackoverflowcollapseab.jpg"CollapsableArea" is of type "Control", containing 2 extra private properties:
- "CollapsableControl"
- "Panel"
i thought it would be enough, to redirect the getter of the CollapsableArea.Controls to CollapsableArea.Panel.Controls. in CollapsableArea.CreateChildControls() i instanciate and add the CollapsableControl and Panel to base.Controls and in CollapsableArea.RenderChildren() render those 2
my problems now: the CollapsableControl will get a clientID (without setting an ID) - the panel won't render CollapsableControl will fail (or passed out), if panel contains <% %>-tags
any suggestions?
edit: i fixed the behaviour of the missing ID - just set CollapsableControl.AssociatedControlID to Panel.ClientID... but - when putting <% %> in the panel, it won't get rendered??!!
If you are after a simple panel, rather then re-inventing the wheel you could use the Collapsible Panel Control:
http://www.asp.net/AJAX/AjaxControlToolkit/Samples/CollapsiblePanel/CollapsiblePanel.aspx
Might be the easiest way to get the functionality you are after?
oh, how comes - i've solved this problem:
public sealed class CollapsableArea : Control
{
private const string ViewStateKeyCollapsableContentClientID = "collapsableContentClientID";
private string CollapsableContentClientID
{
get
{
var obj = this.ViewState[ViewStateKeyCollapsableContentClientID];
if (obj == null)
{
var collapsableContentClientID = Guid.NewGuid().ToString();
this.ViewState[ViewStateKeyCollapsableContentClientID] = collapsableContentClientID;
return collapsableContentClientID;
}
return (string)obj;
}
}
/// <summary>
/// Gets or sets the header text.
/// </summary>
/// <value>The header text.</value>
public string HeaderText
{
get
{
this.EnsureChildControls();
return this._collapseControl.Text;
}
set
{
this.EnsureChildControls();
this._collapseControl.Text = value;
}
}
public override ControlCollection Controls
{
get
{
// redirect controls
return this._collapsableContent.Controls;
}
}
#region child controls
private readonly Panel _collapsableContent = new Panel();
private readonly CollapsableControl _collapseControl = new CollapsableControl();
#endregion
public override Control FindControl(string id)
{
// need to redirect
if (string.Equals(id, this._collapsableContent.ID))
{
return this._collapsableContent;
}
return this._collapsableContent.FindControl(id);
}
protected override void CreateChildControls()
{
base.Controls.Clear();
var collapsableContentClientID = this.CollapsableContentClientID;
this._collapsableContent.ID = collapsableContentClientID;
this._collapseControl.AssociatedControlID = collapsableContentClientID;
base.Controls.Add(this._collapseControl);
base.Controls.Add(this._collapsableContent);
}
protected override void RenderChildren(HtmlTextWriter writer)
{
this._collapseControl.RenderControl(writer);
// hack for code blocks
if (!this.Controls.IsReadOnly)
{
this._collapsableContent.RenderControl(writer);
}
else
{
this._collapsableContent.RenderBeginTag(writer);
base.RenderChildren(writer);
this._collapsableContent.RenderEndTag(writer);
}
}
}
Your control should get a Template control property to define collapsable content. And as you said a AssociatedControlID property which gets the Label control id.
public class CollapsableArea : WebControl, INamingContainer
{
public string AssociatedControlID { get; set; }
public ITemplate ContentTemplate { get; set; }
}
You have to register a jquery to the startup scripts of the page.
$("#The AssociatedControlID client control id").click(function(e) {
$("#The CollapsableArea client control id").toggle();
}
精彩评论