ASP.NET 2.0 - Losing controls added in post back

M

Michael Lang

I'm adding checkbox controls to a panel in a post back, I then have a second
post back in which I attempt to process the checkbox controls however they
seem to have disappeared off the panel. The following code demonstrates
what I'm trying to do.

Can anyone explain why there is no checkbox control on the panel when btnTwo
is clicked?

default.aspx:----------------------------------------------------------------------------------------------

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>

<!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>
<asp:panel ID="pnlTest" runat="server"></asp:panel>
<asp:Button ID="btnOne" runat="server" Text="Next>"
OnClick="btnOne_Click" />
<asp:Button ID="btnTwo" runat="server" Text="Save" Visible ="false"
OnClick="btnTwo_Click" />
<br />
<asp:Label ID="Label1" runat="server"
Text="Label"></asp:Label></div>
</form>
</body>
</html>

-----------------------------------------------------------------------------------------------------------

default.aspx.cs:--------------------------------------------------------------------------------------------

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}

protected void btnOne_Click(object sender, EventArgs e)
{
btnOne.Visible = false;
CheckBox chkTest = new CheckBox();
chkTest.ID = "m";
chkTest.Text = "CheckMe";
btnTwo.Visible = true;

pnlTest.Controls.Add(chkTest);
}
protected void btnTwo_Click(object sender, EventArgs e)
{
if (pnlTest.Controls.Count < 1)
{
Label1.Text = "Failed";
return;
}

Control control = pnlTest.FindControl("m");
CheckBox chkTest = control as CheckBox;
if (chkTest.Checked)
Label1.Text = "Worked";
}
}
 
M

Michael Lang

Thanks...

Quite right.

I thought perhaps by re-adding the controls their state would be lost but
through testing this looks not to be the case. So for anyone interested the
following code works...

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (btnTwo.Visible)
{
CheckBox chkTest = new CheckBox();
chkTest.ID = "m";
chkTest.Text = "CheckMe";
pnlTest.Controls.Add(chkTest);
}
}

protected void btnOne_Click(object sender, EventArgs e)
{
btnOne.Visible = false;
btnTwo.Visible = true;

CheckBox chkTest = new CheckBox();
chkTest.ID = "m";
chkTest.Text = "CheckMe";

pnlTest.Controls.Add(chkTest);
}
protected void btnTwo_Click(object sender, EventArgs e)
{
if (pnlTest.Controls.Count < 1)
{
Label1.Text = "Failed";
return;
}

Control control = pnlTest.FindControl("m");
CheckBox chkTest = control as CheckBox;
if (chkTest.Checked)
Label1.Text = "Is Checked";
else
Label1.Text = "Not Checked";
}
}


Eliyahu Goldin said:
Michael,

You have to re-create dynamically-created controls on every postback.

Find more here:
http://aspnet.4guysfromrolla.com/articles/092904-1.aspx

--
Eliyahu Goldin,
Software Developer & Consultant
Microsoft MVP [ASP.NET]
http://msmvps.com/blogs/egoldin


Michael Lang said:
I'm adding checkbox controls to a panel in a post back, I then have a
second post back in which I attempt to process the checkbox controls
however they seem to have disappeared off the panel. The following code
demonstrates what I'm trying to do.

Can anyone explain why there is no checkbox control on the panel when
btnTwo is clicked?

default.aspx:----------------------------------------------------------------------------------------------

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>

<!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>
<asp:panel ID="pnlTest" runat="server"></asp:panel>
<asp:Button ID="btnOne" runat="server" Text="Next>"
OnClick="btnOne_Click" />
<asp:Button ID="btnTwo" runat="server" Text="Save" Visible
="false" OnClick="btnTwo_Click" />
<br />
<asp:Label ID="Label1" runat="server"
Text="Label"></asp:Label></div>
</form>
</body>
</html>

-----------------------------------------------------------------------------------------------------------

default.aspx.cs:--------------------------------------------------------------------------------------------

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}

protected void btnOne_Click(object sender, EventArgs e)
{
btnOne.Visible = false;
CheckBox chkTest = new CheckBox();
chkTest.ID = "m";
chkTest.Text = "CheckMe";
btnTwo.Visible = true;

pnlTest.Controls.Add(chkTest);
}
protected void btnTwo_Click(object sender, EventArgs e)
{
if (pnlTest.Controls.Count < 1)
{
Label1.Text = "Failed";
return;
}

Control control = pnlTest.FindControl("m");
CheckBox chkTest = control as CheckBox;
if (chkTest.Checked)
Label1.Text = "Worked";
}
}

-----------------------------------------------------------------------------------------------------------

Thanks in advance...

Michael
 
M

Mark Rae

following code works...
protected void Page_Load(object sender, EventArgs e)

In which case, you're quite fortunate...

Generally speaking, in order to pretty much guarantee that such code will
work, you need to create the dynamic controls in Page_Init, not Page_Load...
 
M

Michael Lang

This would be because viewstate is loaded after the init and before the
load.

OK so my code needs a little rework.

It makes it a bit of a chicken and egg problem when dealing with content
dynamically generated based on previous input from the user, especially if
you want this content to retain viewstate. I guess the answer is to persist
input from the user between requests.....

Hmm... I'm looking forward to the day I can suggest using XBAP instead of
Web Apps.
 
J

Joe (MCAD)

Michael said:
This would be because viewstate is loaded after the init and before the
load.

OK so my code needs a little rework.

It makes it a bit of a chicken and egg problem when dealing with content
dynamically generated based on previous input from the user, especially if
you want this content to retain viewstate. I guess the answer is to persist
input from the user between requests.....

Hmm... I'm looking forward to the day I can suggest using XBAP instead of
Web Apps.

This is incorrect, you don't need to manually recreate the dynamic
controls on postback to have them work. Instead use the LoadViewState
and SaveViewState methods to remember and create what your dynamic
controls are/were. Warning, this is add some viewstate weight.
 
M

Mark Rae

Warning, this is add some viewstate weight.

That's the understatement of the year!

I've never used the LoadViewState and SaveViewState methods precisely
because of the ViewState bloat they cause...
 
M

Michael Lang

I've not used these methods before. They appear to be used for customising
the processing of loading and saving the viewstate of a control. I'm not
sure exactly what you're proposing here or what alternative solution they
facilitate.

Can you elaborate a little? Perhaps with a code example.
 
M

Michael Lang

I've managed to move all my dynamically generated content to the page_init
as you've suggested so I've pretty much got this sorted. I'm only
continuing this for academic purposes. The ASP.NET lifecycle goes...

Init
Load ViewState
Load post back data from the form
Page_Load
Raise events due to post back data
Save ViewState
Render

I understand now creating the dynamic content in the page_load worked only
because of the type of controls I chose which seem to be processing data
posted back in the form in the Raise PostBack event phase which occurs after
the page_load. Some controls only process data posted in the form before
the page_load, in that case or if your dynamic content required viewstate
data then using the page_load isn't going to work.

I'm guessing if you had a scenario where your dynamically generated content
was based on data input from the user then you might opt to separate the
functionality into separate pages or use session state instead of ViewState
to keep state information about the content.
 
M

Michael Lang

I've always avoided using ViewState all together hence a lot of the issues
we're discussing relating to the loading and saving of viewstate I've not
dealt with before, which also might explain my "Luck".
 
M

Michael Lang

P.S

Can anyone give examples of controls which only load post back form data
before the page load ?
 
M

Mark Rae

Can anyone give examples of controls which only load post back form data
before the page load ?

DropDownList.

In order for them to work properly across postback, their datasource must be
populated in Page_Init, otherwise their selected value will be lost.
 
M

Michael Lang

My testing seems to suggest otherwise....

The following code does not lose the selected value. I think this is
because the dropdownlist fires the event selectedindexchanged after the page
load....

Try this code...

default.aspx:----------------------------------------------------------------------------

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs"
Inherits="_Default" %>

<!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>
<asp:panel ID="pnlTest" runat="server"></asp:panel>
<asp:Button ID="btnOne" runat="server" Text="Next>"
OnClick="btnOne_Click" />
<asp:Button ID="btnTwo" runat="server" Text="Save" Visible ="false"
OnClick="btnTwo_Click" />
<br />
<asp:Label ID="Label1" runat="server"
Text="Label"></asp:Label></div>
<asp:Label ID="Label2" runat="server"
Text="Label"></asp:Label></div>
</form>
</body>
</html>

Default.aspx.cs------------------------------------------------------------------------------

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Init(object sender, EventArgs e)
{

}

protected void Page_Load(object sender, EventArgs e)
{
if (btnTwo.Visible)
{
GenerateContent();
DropDownList dropTest = pnlTest.FindControl("n") as
DropDownList;
string sel = dropTest.SelectedValue;
}
}

private void GenerateContent()
{
CheckBox chkTest = new CheckBox();
chkTest.ID = "m";
chkTest.Text = "CheckMe";
pnlTest.Controls.Add(chkTest);

DropDownList dropDown = new DropDownList();
dropDown.ID = "n";
dropDown.Items.Add("Selection one");
dropDown.Items.Add("Selection two");
dropDown.Items.Add("Selection three");

pnlTest.Controls.Add(dropDown);
pnlTest.Controls.Add(chkTest);
}

protected override void RaisePostBackEvent(IPostBackEventHandler
sourceControl, string eventArgument)
{
base.RaisePostBackEvent(sourceControl, eventArgument);
}

protected void btnOne_Click(object sender, EventArgs e)
{
btnOne.Visible = false;
btnTwo.Visible = true;

GenerateContent();
}
protected void btnTwo_Click(object sender, EventArgs e)
{
if (pnlTest.Controls.Count < 1)
{
Label1.Text = "Failed";
return;
}

Control control = pnlTest.FindControl("m");
CheckBox chkTest = control as CheckBox;
if (chkTest.Checked)
Label1.Text = "Worked";

control = pnlTest.FindControl("n");
DropDownList dropTest = control as DropDownList;
Label2.Text = dropTest.SelectedValue;
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,983
Messages
2,570,187
Members
46,747
Latest member
jojoBizaroo

Latest Threads

Top