2009-11-10 81 views
2

这让我完全不解,谁能解释一下?Viewstate - 完全混淆。

标记:

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

代码背后:

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

当我改变在这两个文本框中的文字,然后点击“点击”按钮,在txtTest文本将恢复到原来的值'BBB'(在page_load中指定),但动态文本框保留刚刚输入的值(而不是'AAA'),尽管它与另一个'硬编码'文本框同时指定。

+0

我认为,我们的编码在后.NET 1.0/1.1的时代,请参阅相关的一个帖子在这里得到更好的理解添加动态控制的性质:http://stackoverflow.com/questions/ 1708264/add-dynamic-controls-in-asp-net-is-there-a-difference-between-1-1-and-2-0 – 2009-11-10 14:20:00

+1

我猜测这不是1.0/1.1时代代码,因为他用来添加动态控件的语法。 – 2009-11-10 14:45:59

回答

3

txtTest的值在您的Page_Load事件中被覆盖,所以您将看不到ViewState值。 ViewState值在PreLoad阶段加载。

动态控件的值接收ViewState值,因为您正在设置文本,然后将控件添加到页面。当控件被添加到页面时,它会跟上它的事件。在此追赶过程中,该值将从ViewState中加载,并覆盖初始值。

杰夫西尔的代码不起作用,因为直到您退出Page_Load时,控件才会起作用。如果你绑定到新的TextBox的Load事件并引入一对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"); 
} 
0

您需要在Page_Load之前添加新的TextBox控件(例如,在Page_Init之内但不在之前)。

“静态”文本框的默认值只需要初始化一次(例如在! IsPostback之内)Page_Load

看看Page Lifecycle

+0

不一定。 ASP.NET也调用新控件的所有事件(init,load viewstate等)。它在你将控件添加到页面的那一刻就这样做了。 – 2009-11-10 13:46:22

+0

@Vilx:你说的对,它适用于这种情况。这让我想知道一个新问题。为什么MS'鼓励'在Page_Load之前添加动态控件? – 2009-11-10 14:02:53

+0

好吧,我已经在这里发布的问题:http://stackoverflow.com/questions/1708264/add-dynamic-controls-in-asp-net-is-there-a-difference-between-1-1-and -2-0 – 2009-11-10 14:14:46

1

我认为你应该把作为new TextBox()代码中,Text属性的值在TextBox设置之前它被添加到页面,设置内部if(!IsPostBack)

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

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

文本代码因此它会在回发中保留用户对文本的更改。

+0

你走在正确的道路上,但它有点不同。第一部分是正确的 - 缺少“if(!IsPostBack)”是第一个文本框混乱了。然而,第二个文本框并没有受到这个影响,因为它的Text属性在它被添加到页面之前被设置(与第一个不同)。 – 2009-11-10 13:47:59

+0

@Vilx - 好点。现在更新 – 2009-11-10 13:53:53

3

静态文本框必须使用!IsPostBack检查仅初始化一次。

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

动态文本框保留其值,因为Viewstate在添加到PlaceHolder控件集合时应用于其上。

如果你这样做,而不是,修改后的值会丢失:

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

编辑: 正如迈克Ĵ提到,前面的代码示例是错误的。

杰夫CYR的代码不起作用,因为 直到退出的Page_Load控制不追赶 。

+0

所以在我调用.add(txt)方法之后,像'load pagestate if life cycle <= page_load()? – maxp 2009-11-10 14:12:49

+0

此代码不起作用,我输入的值在回发后仍然保留。 – maxp 2009-11-10 14:25:20

+0

你是对的,我没有在发布之前测试我的代码,对我感到羞耻:) Mike J.展示了为什么我的代码在他的回答下面不起作用。 – 2009-11-10 15:11:41

1

除了从o.k.w回答。

从下面的代码开始学习。

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

@萨尔:谢谢你在我的回答之上骑行,但我的遗憾是不幸的:P – 2009-11-10 14:32:54

+0

@ o.k.w .:对不起,我不是故意的。 – Saar 2009-11-10 15:09:05

+0

@Saar:不用担心,我不是故意的:) – 2009-11-10 15:31:59

0

我看到两个问题与得到的ViewState到动态添加文本框。

  1. 在ViewState应用到动态控件之前,正在创建和更新控件。这将发生在Page_Load之后,但在按钮单击事件之前。这就是为什么你的文本值被写入。
  2. 要一致地发布ViewState,您需要为动态添加的控件分配一个不会更改的ID。否则,当页面获得更多动态控件时,您将会看到ViewState无法按预期应用的时间。
+0

@Jeff:您可能会对我发布的与此相关的新问题感兴趣。在我的问题上看到我的评论。我想给你+1,但我现在真的不确定:P – 2009-11-10 14:28:51

+0

@ o.k.w. - 我用1.1做了很长时间,我不确定你是否可以在PAGE_LOAD期间安全地添加控件,或者如果你必须使用PreInit。否则,我会参加那个讨论。 – 2009-11-10 19:57:29