Problem with dynamically created controls, not working as expected

X

Xaroth

I am attempting to create a database-driven web survey system where the
questions themselves are stored in the database. In having a page where the
controls are generated dynamically based on the type of question being asked,
I'm running into a very odd and very frustrating problem.

I have boiled the problem down to the code shown below. The page described
below is simple enough: there is a label, whose text is simply an integer
showing which "question" we're on. Then, there is a control of varying type
which is dynamically created based on which "question" we're on. Finally,
there are "Next" and "Previous" buttons that increment and decrement the
"question" number, respectively.

The problem being encountered is this:
When you start, the page reads question 0, as expected. When you click
"Next", the expected behaviour is that the question label will be updated to
read "1", and the question will change. This does not occur.

Instead, nothing happens. When you then click EITHER button, the number
increments. Then, when you press either button, the behaviour follows what
you pressed last time - that is, the updates to the page are always one click
behind what you've entered.

I have searched and been unable to find anything that describes the problem
I'm having. Any assistance with this will be greatly appreciated.

....and now for the code. The project can be constructed from a blank C#
ASP.Net project. Add a single panel (named Panel1) to the design page.
Then, add the code below to the code page. No other changes are necessary to
observe the problem I'm describing.

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here

// Clear out the existing controls, since the new ones won't be the same
types as in the previous question.
Panel1.Controls.Clear();

// Add the Question number label
Label aLabel = new Label();
if( Session["Num"] == null )
Session["Num"] = "0";

aLabel.Text = (string)(Session["Num"]);
aLabel.ID = "aLabel";
Panel1.Controls.Add( aLabel );

// Add a line break
LiteralControl aLC = new LiteralControl( "<BR><BR>" );
aLC.ID = "aLC";
Panel1.Controls.Add( aLC );

// Add a control based on the Question number. In my real code,
// the type of question and question text, etc. are loaded dynamically
// from a database. This emulates that process somewhat.

switch( int.Parse( (string)(Session["Num"]) ) % 3 )
{
case 0:
Label l2 = new Label();
l2.ID = "l2";
l2.Text = "Label2";
Panel1.Controls.Add( l2 );
break;
case 1:
Button b2 = new Button();
b2.ID = "b2";
b2.Text = "Don't click";
Panel1.Controls.Add( b2 );
break;
case 2:
TextBox aTB = new TextBox();
aTB.ID = "aTB";
aTB.Text = "Texty.";
Panel1.Controls.Add( aTB );
break;
}

// Add a linebreak
LiteralControl aLC2 = new LiteralControl( "<BR><BR>" );
aLC2.ID = "aLC2";
Panel1.Controls.Add( aLC2 );

// Add the previous and next buttons. These are added dynamically
// because we don't know until runtime what text is going to be
// displayed in the buttons. However, please note that moving these to
// static controls outside of the Panel1 control did not appear to change
// the exhibited behaviour.

Button prevButton = new Button();
prevButton.ID = "prevButton";
prevButton.Text = "Previous";
prevButton.Click += new EventHandler(prevButton_Click);
Panel1.Controls.Add( prevButton );

Button nextButton = new Button();
nextButton.ID = "nextButton";
nextButton.Text = "Next";
nextButton.Click += new EventHandler(nextButton_Click);
Panel1.Controls.Add( nextButton );
}


private void nextButton_Click(object sender, EventArgs e)
{
// Increment the question number
if( Session["Num"] == null )
Session["Num"] = "0";

int temp = int.Parse( (string)(Session["Num"]) );
temp++;
Session["Num"] = temp.ToString();

// There's no need to force the panel to remake its controls,
// since those will be created based on the new question number
// as a result of the Page_Load() handler after the button is pressed.
}

private void prevButton_Click(object sender, EventArgs e)
{
// Decrement the question number
if( Session["Num"] == null )
Session["Num"] = "0";

int temp = int.Parse( (string)(Session["Num"]) );
temp--;
Session["Num"] = temp.ToString();
}
 
R

Robert Burks

This has to do with the order that the events are being performed. The text
for the label is being set before the button events take place. You can
resolve this one of two ways. Either by Response.Redirect/Server.Transfer
which causes the page to be processed again, or by setting the text value of
the label in the events. The code sample below shows how to do this. Add
this to your click events.

System.Web.UI.WebControls.Label label;
Label=(System.Web.UI.WebControls.Label)Panel1.FindControl("aLabel");
label.Text=temp.ToString();

--
Robert

Xaroth said:
I am attempting to create a database-driven web survey system where the
questions themselves are stored in the database. In having a page where the
controls are generated dynamically based on the type of question being asked,
I'm running into a very odd and very frustrating problem.

I have boiled the problem down to the code shown below. The page described
below is simple enough: there is a label, whose text is simply an integer
showing which "question" we're on. Then, there is a control of varying type
which is dynamically created based on which "question" we're on. Finally,
there are "Next" and "Previous" buttons that increment and decrement the
"question" number, respectively.

The problem being encountered is this:
When you start, the page reads question 0, as expected. When you click
"Next", the expected behaviour is that the question label will be updated to
read "1", and the question will change. This does not occur.

Instead, nothing happens. When you then click EITHER button, the number
increments. Then, when you press either button, the behaviour follows what
you pressed last time - that is, the updates to the page are always one click
behind what you've entered.

I have searched and been unable to find anything that describes the problem
I'm having. Any assistance with this will be greatly appreciated.

...and now for the code. The project can be constructed from a blank C#
ASP.Net project. Add a single panel (named Panel1) to the design page.
Then, add the code below to the code page. No other changes are necessary to
observe the problem I'm describing.

private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here

// Clear out the existing controls, since the new ones won't be the same
types as in the previous question.
Panel1.Controls.Clear();

// Add the Question number label
Label aLabel = new Label();
if( Session["Num"] == null )
Session["Num"] = "0";

aLabel.Text = (string)(Session["Num"]);
aLabel.ID = "aLabel";
Panel1.Controls.Add( aLabel );

// Add a line break
LiteralControl aLC = new LiteralControl( "<BR><BR>" );
aLC.ID = "aLC";
Panel1.Controls.Add( aLC );

// Add a control based on the Question number. In my real code,
// the type of question and question text, etc. are loaded dynamically
// from a database. This emulates that process somewhat.

switch( int.Parse( (string)(Session["Num"]) ) % 3 )
{
case 0:
Label l2 = new Label();
l2.ID = "l2";
l2.Text = "Label2";
Panel1.Controls.Add( l2 );
break;
case 1:
Button b2 = new Button();
b2.ID = "b2";
b2.Text = "Don't click";
Panel1.Controls.Add( b2 );
break;
case 2:
TextBox aTB = new TextBox();
aTB.ID = "aTB";
aTB.Text = "Texty.";
Panel1.Controls.Add( aTB );
break;
}

// Add a linebreak
LiteralControl aLC2 = new LiteralControl( "<BR><BR>" );
aLC2.ID = "aLC2";
Panel1.Controls.Add( aLC2 );

// Add the previous and next buttons. These are added dynamically
// because we don't know until runtime what text is going to be
// displayed in the buttons. However, please note that moving these to
// static controls outside of the Panel1 control did not appear to change
// the exhibited behaviour.

Button prevButton = new Button();
prevButton.ID = "prevButton";
prevButton.Text = "Previous";
prevButton.Click += new EventHandler(prevButton_Click);
Panel1.Controls.Add( prevButton );

Button nextButton = new Button();
nextButton.ID = "nextButton";
nextButton.Text = "Next";
nextButton.Click += new EventHandler(nextButton_Click);
Panel1.Controls.Add( nextButton );
}


private void nextButton_Click(object sender, EventArgs e)
{
// Increment the question number
if( Session["Num"] == null )
Session["Num"] = "0";

int temp = int.Parse( (string)(Session["Num"]) );
temp++;
Session["Num"] = temp.ToString();

// There's no need to force the panel to remake its controls,
// since those will be created based on the new question number
// as a result of the Page_Load() handler after the button is pressed.
}

private void prevButton_Click(object sender, EventArgs e)
{
// Decrement the question number
if( Session["Num"] == null )
Session["Num"] = "0";

int temp = int.Parse( (string)(Session["Num"]) );
temp--;
Session["Num"] = temp.ToString();
}
 

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,764
Messages
2,569,564
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top