I'm trying to make a control where I can add panels that become (in)visible under certain circumstances. As a prototype I created a test control that holds panels as child controls, which can contain child controls. To load the panels, I created a ControlBuilder.
Everything works fine, except for one thing: the ViewState of child controls within the panels is not retained. I checked the whole cycle, and all seems well... values on the controls change, etc. etc. But when the page reloads after a postback, no ViewState is loaded.
The wierdest thing is that to track what happens inside a TextBox in one of the panels, I created a control that inherits from TextBox. If I only inherit (as follows), the inherited control retains i's ViewState, while the TextBox does not!
public class TestBox : System.Web.UI.WebControls.TextBox {}
I have included the full prototype code below, and I hope someone can shed some light on the matter. BTW, I know controls that are not visible by default do not save ViewState, so I already tried code to override this behavior. That did not work, and judging from the TestBox example, that shouldn't be necessary anyway in this solution.
The C# code
using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace Dev.WebControls
{
[ParseChildren(false)]
[ControlBuilder(typeof(TestControlBuilder))]
public class TestControl : WebControl, IPostBackEventHandler
{
protected int SelectedPanelIndex
{
get
{
object o = ViewState["SelectedPanelIndex"];
if(o == null) return 0;
return (int)o;
}
set
{
ViewState["SelectedPanelIndex"]= value;
}
}
public override ControlCollection Controls
{
get
{
this.EnsureChildControls();
return base.Controls;
}
}
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
for(int i = 0; i < this.Controls.Count; i++)
{
Panel panel = (Panel)this.Controls[i];
writer.AddAttribute(HtmlTextWriterAttribute.Href, Page.GetPostBackClientHyperlink(this, i.ToString()));
writer.RenderBeginTag(HtmlTextWriterTag.A);
writer.Write(panel.ID);
writer.RenderEndTag();
if(this.SelectedPanelIndex != i)
{
panel.Visible = false;
}
writer.WriteFullBeginTag("br");
}
writer.WriteFullBeginTag("hr");
base.RenderContents(writer);
foreach(Control control in this.Controls)
{
if(control is Panel) control.Visible = true;
}
}
#region IPostBackEventHandler Members
public void RaisePostBackEvent(string eventArgument)
{
this.SelectedPanelIndex = Convert.ToInt32(eventArgument);
}
#endregion
}
public class TestControlBuilder : ControlBuilder
{
public override bool AllowWhitespaceLiterals()
{
return false;
}
public override Type GetChildControlType(string tagName, System.Collections.IDictionary attribs)
{
if(string.Compare(tagName, "asp:Panel", true) == 0)
{
return typeof(Panel);
}
else
{
throw new ApplicationException("Only panels are allowed as child controls.");
}
}
}
}
The ASPX
<%@ Register TagPrefix="cc1" Namespace="Dev.WebControls" Assembly="Dev.WebControls" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<body>
<form id="Form1" method="post" runat="server">
<cc1:TestControl id="TestControl1" runat="server">
<asp:panel id="Panel1" runat="server">
<cc1:TestBox ID="TestBox1" Runat="server">123</cc1:TabBox>
<asp:TextBox ID="Textbox1" Runat="server">456</asp:TextBox>
</asp:panel>
<asp:panel id="Panel2" runat="server">
<asp:TextBox ID="Textbox2" Runat="server">789</asp:TextBox>
</asp:panel>
</cc1:TestControl>
</form>
</body>
</HTML>
Michiel van Otegem
http://www.aspnl.com
http://www.aspalliance.com/michiel
---
Teach Yourself XSLT in 21 Days
http://www.amazon.com/exec/obidos/ASIN/0672323184/aspnlcom-20