S
Steve Drake
All,
I have a CONTROL that contains 1 control (Control ONE), the 1 control that
it can contain 1 or 2 control (Control A and B).
Control A, raises and event and Control ONE receives this event and this
causes control B to be created, when this is done the VIEWSTATE is lost for
CONTROL B.
In the EVENT that causes CONTROL B to be created I have to set
ChildControlsCreated to false, if I don't set it the viewstate works but the
control doesn't show, as the createchild controls does not get re-ran.
Below is the a smaller version of the code that I have created to reproduce
the problem test as follows :
Click Get Current Time, it will now show the time
Click do post back, it will still show time in first step, as well as time
of post back, to prove its posted back.
Click Raise Event, it has now lost the viewstate, time has gone blank.
Click Get Current Time on both line, you will see the time get filled in and
it persisted in the viewstate, do a few clicks to prove this.
Now Click Raise Event, view state has been lost again.
Cheers
Steve
Project name should be ViewStateTest
Code : (Add to single class called controls.cs)
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ViewStateTest
{
public class ContainTime : WebControl ,INamingContainer
{
ShowTime showtimeA;
ShowTime showtimeB;
WebControl holdingcontrol;
bool showB;
protected override void LoadViewState(object savedState)
{
base.LoadViewState (savedState);
if (ViewState["ShowB"] == null)
{
showB = false;
}
else
{
showB = (bool) ViewState["ShowB"];
}
}
protected override object SaveViewState()
{
ViewState["ShowB"] = showB;
return base.SaveViewState ();
}
protected override void CreateChildControls()
{
Controls.Clear();
showtimeA = new ShowTime();
showtimeA.Click+=new EventHandler(showtimeA_Click);
Controls.Add(showtimeA);
if (showB )
{
showtimeB = new ShowTime();
Controls.Add(showtimeB);
}
}
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
showtimeA.RenderControl(writer);
if (showB) showtimeB.RenderControl(writer);
}
public ContainTime()
{
}
private void showtimeA_Click(object sender, EventArgs e)
{
this.showB = !showB;
this.ChildControlsCreated = false; // if I dont do this, the control is
there
// its the above line that makes the viewstate vanish, but I need it to
cause the controls to dynamicly add.
}
}
/// <summary>
/// Summary description for ShowTime.
/// </summary>
public class ShowTime : WebControl,INamingContainer
{
public ShowTime()
{
}
string timestring;
Button abutton;
Button getTimeButton;
Button doRoundTrip;
Label timelabel;
public event EventHandler Click;
protected override void LoadViewState(object savedState)
{
base.LoadViewState (savedState);
System.Diagnostics.Trace.WriteLine("Items in viewstate " +
ViewState.Count);
if (ViewState["time"] == null)
{
timestring = "Not found";
}
else
{
timestring = (string) ViewState["time"];
}
}
protected override object SaveViewState()
{
ViewState["time"] = timestring;
return base.SaveViewState ();
}
protected override void CreateChildControls()
{
// For this example we could just write the time out in the render, but I
need to mimic the class
// that I am having problems with as much as possable.
Controls.Clear();
timelabel = new Label();
timelabel.Text = timestring;
abutton = new Button();
abutton.Text = "Raise Event";
abutton.Click+=new System.EventHandler(abutton_Click);
getTimeButton = new Button();
getTimeButton.Text = "Get Current Time";
getTimeButton.Click+=new EventHandler(getTimeButton_Click);
doRoundTrip = new Button();
doRoundTrip.Text = "Do Post Back";
doRoundTrip.Click+=new EventHandler(doRoundTrip_Click);
Controls.Add(timelabel);
Controls.Add(abutton);
Controls.Add(getTimeButton);
Controls.Add(doRoundTrip);
}
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
writer.RenderBeginTag("DIV");
writer.Write(this.UniqueID);
EnsureChildControls();
timelabel.RenderControl(writer);
abutton.RenderControl(writer);
getTimeButton.RenderControl(writer);
writer.Write("Time of post back " + System.DateTime.Now.ToString());
doRoundTrip.RenderControl(writer);
writer.RenderEndTag();
}
private void abutton_Click(object sender, System.EventArgs e)
{
Click(this,e);
}
private void getTimeButton_Click(object sender, EventArgs e)
{
this.timestring = System.DateTime.Now.ToString();
ChildControlsCreated=false;
}
private void doRoundTrip_Click(object sender, EventArgs e)
{
System.Diagnostics.Trace.WriteLine("Round trip");
ChildControlsCreated=false;
}
}
}
CODE BEHIND CODE
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace ViewStateTest
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected ViewStateTest.ContainTime ContainTime1;
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
}
}
ASPX PAGE :
<%@ Register TagPrefix="cc1" Namespace="ViewStateTest"
Assembly="ViewStateTest" %>
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"
Inherits="ViewStateTest.WebForm1" smartNavigation="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<cc1:ContainTime id="ContainTime1" style="Z-INDEX: 101; LEFT: 56px;
POSITION: absolute; TOP: 48px"
runat="server"></cc1:ContainTime>
</form>
</body>
</HTML>
I have a CONTROL that contains 1 control (Control ONE), the 1 control that
it can contain 1 or 2 control (Control A and B).
Control A, raises and event and Control ONE receives this event and this
causes control B to be created, when this is done the VIEWSTATE is lost for
CONTROL B.
In the EVENT that causes CONTROL B to be created I have to set
ChildControlsCreated to false, if I don't set it the viewstate works but the
control doesn't show, as the createchild controls does not get re-ran.
Below is the a smaller version of the code that I have created to reproduce
the problem test as follows :
Click Get Current Time, it will now show the time
Click do post back, it will still show time in first step, as well as time
of post back, to prove its posted back.
Click Raise Event, it has now lost the viewstate, time has gone blank.
Click Get Current Time on both line, you will see the time get filled in and
it persisted in the viewstate, do a few clicks to prove this.
Now Click Raise Event, view state has been lost again.
Cheers
Steve
Project name should be ViewStateTest
Code : (Add to single class called controls.cs)
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ViewStateTest
{
public class ContainTime : WebControl ,INamingContainer
{
ShowTime showtimeA;
ShowTime showtimeB;
WebControl holdingcontrol;
bool showB;
protected override void LoadViewState(object savedState)
{
base.LoadViewState (savedState);
if (ViewState["ShowB"] == null)
{
showB = false;
}
else
{
showB = (bool) ViewState["ShowB"];
}
}
protected override object SaveViewState()
{
ViewState["ShowB"] = showB;
return base.SaveViewState ();
}
protected override void CreateChildControls()
{
Controls.Clear();
showtimeA = new ShowTime();
showtimeA.Click+=new EventHandler(showtimeA_Click);
Controls.Add(showtimeA);
if (showB )
{
showtimeB = new ShowTime();
Controls.Add(showtimeB);
}
}
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
showtimeA.RenderControl(writer);
if (showB) showtimeB.RenderControl(writer);
}
public ContainTime()
{
}
private void showtimeA_Click(object sender, EventArgs e)
{
this.showB = !showB;
this.ChildControlsCreated = false; // if I dont do this, the control is
there
// its the above line that makes the viewstate vanish, but I need it to
cause the controls to dynamicly add.
}
}
/// <summary>
/// Summary description for ShowTime.
/// </summary>
public class ShowTime : WebControl,INamingContainer
{
public ShowTime()
{
}
string timestring;
Button abutton;
Button getTimeButton;
Button doRoundTrip;
Label timelabel;
public event EventHandler Click;
protected override void LoadViewState(object savedState)
{
base.LoadViewState (savedState);
System.Diagnostics.Trace.WriteLine("Items in viewstate " +
ViewState.Count);
if (ViewState["time"] == null)
{
timestring = "Not found";
}
else
{
timestring = (string) ViewState["time"];
}
}
protected override object SaveViewState()
{
ViewState["time"] = timestring;
return base.SaveViewState ();
}
protected override void CreateChildControls()
{
// For this example we could just write the time out in the render, but I
need to mimic the class
// that I am having problems with as much as possable.
Controls.Clear();
timelabel = new Label();
timelabel.Text = timestring;
abutton = new Button();
abutton.Text = "Raise Event";
abutton.Click+=new System.EventHandler(abutton_Click);
getTimeButton = new Button();
getTimeButton.Text = "Get Current Time";
getTimeButton.Click+=new EventHandler(getTimeButton_Click);
doRoundTrip = new Button();
doRoundTrip.Text = "Do Post Back";
doRoundTrip.Click+=new EventHandler(doRoundTrip_Click);
Controls.Add(timelabel);
Controls.Add(abutton);
Controls.Add(getTimeButton);
Controls.Add(doRoundTrip);
}
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
writer.RenderBeginTag("DIV");
writer.Write(this.UniqueID);
EnsureChildControls();
timelabel.RenderControl(writer);
abutton.RenderControl(writer);
getTimeButton.RenderControl(writer);
writer.Write("Time of post back " + System.DateTime.Now.ToString());
doRoundTrip.RenderControl(writer);
writer.RenderEndTag();
}
private void abutton_Click(object sender, System.EventArgs e)
{
Click(this,e);
}
private void getTimeButton_Click(object sender, EventArgs e)
{
this.timestring = System.DateTime.Now.ToString();
ChildControlsCreated=false;
}
private void doRoundTrip_Click(object sender, EventArgs e)
{
System.Diagnostics.Trace.WriteLine("Round trip");
ChildControlsCreated=false;
}
}
}
CODE BEHIND CODE
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace ViewStateTest
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
protected ViewStateTest.ContainTime ContainTime1;
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
}
}
ASPX PAGE :
<%@ Register TagPrefix="cc1" Namespace="ViewStateTest"
Assembly="ViewStateTest" %>
<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false"
Inherits="ViewStateTest.WebForm1" smartNavigation="True"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
<HEAD>
<title>WebForm1</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema"
content="http://schemas.microsoft.com/intellisense/ie5">
</HEAD>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<cc1:ContainTime id="ContainTime1" style="Z-INDEX: 101; LEFT: 56px;
POSITION: absolute; TOP: 48px"
runat="server"></cc1:ContainTime>
</form>
</body>
</HTML>