asp.netweb-controlsasp.net-webcontrol

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(collapsablePanel);

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:

  1. "CollapsableControl"
  2. "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??!!


Solution

  • 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);
            }
        }
    }