开发者

Viewstate - utter confusion.

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:

protect开发者_运维百科ed 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.


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");
}


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.


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.


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/>");
}


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.


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.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜