ViewState, form fields, labels and Javascript(转)

An interesting question came up on the ASP.NET forums asking why a TextBox which has its value changed by client-side Javascript persists those changes across postbacks, while a Label does not. And in a nut shell, this question covered two of the biggest causes of confusion among newcomers to ASP.NET: the difference between ViewState and IPostBackDataHandler; and the difference between client-side operations and server-side operations.

First a look at the code that was posted by the questioner:

[ASPX]
 1 <% @ Page Language="VB" AutoEventWireup="false" 
 2    CodeFile="ButtonClickWithJavascript.aspx.vb" 
 3    Inherits="ButtonClickWithJavascript" 
%>
 4 <! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
 5     http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >
 6 < html  xmlns ="http://www.w3.org/1999/xhtml"   >
 7 < head  runat ="server" >
 8 < title > Untitled Page </ title >
 9 < script  language ="javascript" >
10function btchange() {
11document.getElementById("Label1").innerText="Javascript changed!";
12document.getElementById("TextBox1").value="Text from Javascript!";
13}

14
</ script >
15 </ head >
16 < body >
17 < form  id ="form1"  runat ="server" >
18 < div >
19 < table >
20 < tr >
21 < td >< asp:Label  id ="Label1"  runat ="server" > Label </ asp:Label >< br >
22 < asp:TextBox  id ="TextBox1"  runat ="server" ></ asp:TextBox >< br >
23 < input  type ="button"  onclick ="btchange();"  value ="Javascript Change"   />
24 </ td >
25 < td >< asp:Label  id ="Label2"  runat ="server" > Label </ asp:Label >< br >
26 < asp:TextBox  id ="TextBox2"  runat ="server" ></ asp:TextBox >< br >
27 < asp:Button  id ="Button1"  runat ="server"  Text ="Button" ></ asp:Button >
28 </ td >
29 </ tr >
30 </ table >
31 </ div >
32 </ form >
33 </ body >
34 </ html >
35
[Code-behind]
 1 Partial Class ButtonClickWithJavascript
 2   Inherits System.Web.UI.Page
 3
 4   Protected Sub Page_Load(ByVal sender As Object, 
 5     ByVal e As System.EventArgs) Handles Me.Load
 6     If Not Page.IsPostBack Then
 7       Label1.Text  =   " Original Label "
 8       TextBox1.Text  =   " Original Text! "
 9     End If
10   End Sub
11   
12   Protected Sub Button1_Click(ByVal sender As Object, 
13     ByVal e As System.EventArgs) Handles Button1.Click
14     Label2.Text  =   " Button changed "
15     TextBox2.Text  =  Now().ToString()
16   End Sub
17 End Class
18

On first load, the page looks like this:

First Page Load

Clicking the "Javascript Change" button calls the client-side btchange() function which results in the text within the label and the first textbox being changed to give this:

Javascript change to label

Clicking "Button" causes a PostBack, and fires the server-side Button1_Click() event, which results in this:

Page posted back

The value of the first TextBox which was changed using Javascript was retained, but the value of the first Label, which was changed by the same Javascript routine, was not retained. So why is this? "Is there a bug in ViewState, which 'forgets' Label values?" asked the questioner. The answer is "No", but to explain this behaviour, a quick overview of ViewState is required, with links to more detailed explanations.

ViewState's job is to manage any changes to the initial state of server controls, if those changes are made programmatically on the server, or if changes made by user interaction are passed to the server. This does not include restoring the values of form inputs such as TextBoxes or the selected item in a CheckBox. There is a common misconception that form values are managed by ViewState. They are not. Never have been. These values are managed and restored purely by IPostBackDataHandler. IPostBackDataHandler is a massive boon to web developers who were brought up on other server-side technologies, such as classic ASP, PHP etc. In the "olden" days, we used to have to manually wire up every form field to display the originally posted value, so that user's weren't presented with an empty form to fill in all over again, if it had failed server-side validation. IPostBackDataHandler means we never have to do that again.

The part that Viewstate plays in the sample page above is easily examined using Fritz Onion's ViewStateDecoder.

On first load, ViewState only contains the Text value for Label1 - "Original Label ".

Viewstate decoded

Again, ViewState is not responsible for form field values, so the Text value of the TextBoxes is not included. The reason why Label1 is incuded in ViewState, but Label2 is not is because Label2's Text value was set in the aspx - at Page Initialisation. Label1's Text value was initially set in the aspx markup as "Label". It was subsequently programmatically changed in Page_Load to "Original Label ". Remember, ViewState's job is to manage any changes to the initial state of server controls, if those changes are made programmatically on the server. Label1 falls into this category. You can test this by removing the Text value of Button1 from the aspx, and setting it in Page_Load to "Button". Now you see that Button1 is added to ViewState on first load also.

When the "Javascript Change" button is clicked, the client-side script alters the Text values of both Label1 and TextBox1. Looking at ViewState now will show no changes from the initial Page_Load. The page has not been posted back, and Javascript cannot alter ViewState, so this is no surprise. When "Button" is clicked, a PostBack is caused. Now looking at ViewState, we can see that Label2 has been included.

Viewstate decoded

This is because it's initial value was programmatically changed in the Button_Click event. There were no changes in value for Label1, so its original value was restored from ViewState. The Text value of neither TextBox ever made it into ViewState at any stage. This property was managed purely by IPostBackDataHandler all the time.

How do we retain client-side changes to values or state of non-form field controls? Anything that happens on the client is totally shielded from the server, unless we let the server know. The server is completely unable to "read" the results of client-side operations, which is just as it should be for security reasons. So we need to let the server know that changes have taken place. One way to do this is to create a hidden field in the page. Hidden fields, being standard form fields will be looked after by IPostBackDataHandler, so any changes in value will be persisted across postbacks. It would be relatively simple to extend the client-side btchange() function to read and write changes to the hidden field, and copy changes to the Label.

转载于:https://www.cnblogs.com/jeffery19830101/archive/2007/12/29/1019348.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值