views:

195

answers:

6

This has me totally puzzled, can anyone explain this?

Markup:

<form id="form1" runat="server">
<asp:TextBox runat="server" ID="txtTest" />
<asp:PlaceHolder runat="server" ID="PlaceHolder1" />
<asp:Button runat="server" Text="Click" />
</form>

Code Behind:

    protected void Page_Load(object sender, EventArgs e)
    {
    txtTest.Text = "BBB";
    PlaceHolder1.Controls.Add(new TextBox() { Text = "AAA" });
    }

When I change the text in both textboxes, then click the 'Click' button, the text in txtTest is reverted back to the original value 'BBB'(specified in page_load), but the dynamic textbox retains the value I just entered (and not 'AAA') despite this being specified at the same time as the other, 'hardcoded' textbox.

A: 

You need to place the adding of the new TextBox control before Page_Load (e.g. within Page_Init but not before).

The default value of the 'static' TextBox need only be initialized once (e.g. within ! IsPostback) of Page_Load.

Take a look at Page Lifecycle.

o.k.w
Not necessarily. ASP.NET calls all the events (init, load viewstate, etc.) for the new control as well. It does that at the moment you add the control to the page.
Vilx-
@Vilx: You are right, it works in this case. That makes me wonder about a new question. Why do MS 'encourage' adding dynamic controls before Page_Load?
o.k.w
Ok, I've posted the question here: http://stackoverflow.com/questions/1708264/add-dynamic-controls-in-asp-net-is-there-a-difference-between-1-1-and-2-0
o.k.w
+1  A: 

I think that you should be putting the code that sets the text inside if(!IsPostBack)

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        txtTest.Text = "BBB";
    }

PlaceHolder1.Controls.Add(new TextBox() { Text = "AAA" });
}

as for the new TextBox() code, the value of the Text property is set on the TextBox before it is added to the Page and therefore it retains user entered changes to the text on postback.

Russ Cam
You are on the right path, but it's a bit different. The first part is correct - the lack of `if (!IsPostBack)` is what messed up the first textbox. However The second textbox didnt suffer from this because it had its Text property set BEFORE it was added to the page (unlike the first one).
Vilx-
@Vilx - good point. Will update now
Russ Cam
+2  A: 

The static textbox must be initialized only once with the !IsPostBack check.

if (!IsPostBack)
{
    txtTest.Text = "BBB";
}

The dynamic textbox retain its value because the Viewstate is applied on it when it is added to the PlaceHolder control collection.

If you did this instead, the modified value would be lost:

TextBox txt = new TextBox();
PlaceHolder1.Controls.Add(txt);
txt.Text = "AAA";

Edit: As mentioned by Mike J, the preceding code sample is wrong.

Jeff Cyr's code doesn't work because the control doesn't play catch-up until you exit Page_Load.

SelflessCoder
So after i call the .add(txt) method an event like 'load pagestate if life cycle <=page_load()?
maxp
This code doesnt work, value i entered is still retained after postback.
maxp
You are right, I didn't test my code before posting it, shame on me :)Mike J. showed why my code doesn't work in his answer below.
SelflessCoder
+1  A: 

in addition to answer from o.k.w.

start from following code to learn.

 <form id="form1" runat="server">
    <div>
        <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_OnClick" />
    </div>
    </form>


 protected void Page_PreInit(object sender, EventArgs e)
        {
            Response.Write("This is PreInit.... <br/>");
        }

        protected void Page_Init(object sender, EventArgs e)
        {
            Response.Write("This is Init... <br/>");
        }

        protected void Page_InitComplete(object sender, EventArgs e)
        {
            Response.Write("This is InitComplte... <br/>");
        }

        protected void Page_PreLoad(object sender, EventArgs e)
        {
            Response.Write("This is PreLoad... <br/>");
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write("This is Load... <br/>");

            Response.Write("IsPostback: " + IsPostBack + " <br/>");

        }

        protected void Page_LoadComplete(object sender, EventArgs e)
        {
            Response.Write("This is LoadComplete... <br/>");
        }

        protected void Page_PreRender(object sender, EventArgs e)
        {
            Response.Write("This is PreRender... <br/>");
        }

        protected void Page_RenderComplete(object sender, EventArgs e)
        {
            Response.Write("This is RenderComplete... <br/>");
        }

        protected void Page_Unload(object sender, EventArgs e)
        {
            //Response.Write("This is Unload... <br/>");
        }

        protected void Button1_OnClick(object sender, EventArgs e)
        {
            Response.Write("This is Button1_OnClick.... <br/>");
        }
Saar
@Saar: Thanks for riding on top of my answer, but mine is discredited unfortunately :P
o.k.w
@o.k.w.: Sorry, I do not mean it.
Saar
@Saar: No worries, I don't mean it in a -ve way :)
o.k.w
A: 

I see two issues with getting ViewState onto the dynamically added text box.

  1. The control is being created and updated before ViewState gets applied to dynamic controls. This will happen after the Page_Load but before your button click event. This is why your Text value is written over.
  2. For ViewState to be posted consistently, you need to assign an id to the dynamically added control that does not change. Otherwise, as the page gets more dynamic controls, you will see times when ViewState won't apply as you expect.
Jeff Siver
@Jeff: you probably will be interested in the new question I posted related to this. See my comment at the question post. I wanted to +1 yours, but I'm really unsure now :P
o.k.w
@ o.k.w. - It's been so long since I did anything with 1.1, I don't remember for sure if you can safely add controls during PAGE_LOAD or if you had to use PreInit. Otherwise, I would've joined into that discussion.
Jeff Siver
+2  A: 

The value for txtTest is being overwritten in your Page_Load event, so you will not see the ViewState value. The ViewState value is loaded in PreLoad stage.

The value for the dynamic control receives the ViewState value because you are setting the text and then adding the control to the page. When the control is added to the page, it will play catch-up with it's events. During this catchup, the value is loaded from the ViewState, overwriting your initial value.

Jeff Cyr's code doesn't work because the control doesn't play catch-up until you exit Page_Load. You can see this if you tie into the new TextBox's Load event and throw in a couple of Response.Writes.

protected void Page_Load(object sender, EventArgs e)
{
    txtTest.Text = "BBB";
    //PlaceHolder1.Controls.Add(new TextBox() { Text = "AAA" });
    TextBox txt = new TextBox();
    txt.Load += new EventHandler(txt_Load);
    PlaceHolder1.Controls.Add(txt);
    Response.Write("page load");
    txt.Text = "AAA";
}

void txt_Load(object sender, EventArgs e)
{
    Response.Write("textbox load");
}
Mike J