比较郁闷的textbox,页面的视图状态

By admin in 茶社 on 2020年1月30日

让我们分析一种典型情况。假设页面有一个文本框服务器控件。我们所期望的是,当页面回发时,该文本框服务器控件自动地被赋予客户端设置的值。然而,为了满足这种相当普通的需求,我们不需要视图状态。考虑如下页面:

今天转一个asp.net程序从vs2003到vs2005,老报错,postback后取不到textbox控件的改变的值,在vs2003下完全正常,在vs2005下就是不行,搞了一上午都不知为啥,于是上网查查,原来是textbox控件的readonly属性做的怪,真的郁闷.asp.net2.0
的这种改动让人无法理解。解决方法详见如下:

<% @Page language=”c#” %>

()

<form runat=”server”>

有时候,我们不希望用户直接编辑TextBox,而是希望通过客户端脚本的方式来设置内容,一般的做法是设置TextBox的属性ReadOnly为true。但在ASP.NET
2.0里有了变化,设置了ReadOnly为true的TextBox,在服务器端不能通过Text属性获取在客户端设置的新内容,在Reflector里比较一下LoadPostData的实现

<asp:textbox runat=”server” enableviewstate=”false”

.NET 1.1中,

id=”theInput” readonly=”false” text=”Type here” />

bool IPostBackDataHandler.LoadPostData(string postDataKey,
NameValueCollection postCollection)
{
      string text1 = this.Text;
      string text2 = postCollection[postDataKey];
      if (!text1.Equals(text2))
      {
            this.Text = text2;
            return true;
      }
      return false;
}

<asp:checkbox runat=”server” enableviewstate=”false”

.NET 2.0中,

id=”theCheck” text=”Check me” />

protected virtual bool LoadPostData(string postDataKey,
NameValueCollection postCollection)
{
      base.ValidateEvent(postDataKey);
      string text1 = this.Text;
      string text2 = postCollection[postDataKey];
      if (!this.ReadOnly && !text1.Equals(text2,
StringComparison.Ordinal))
      {
            this.Text = text2;
            return true;
      }
      return false;
}

<asp:button runat=”server” text=”Click” onclick=”OnPost” />

就可以看出,如果设置了ReadOnly为true,从客户端传回的新的值是不被设置到Text属性的。

</form>

想要保持.NET
1.*中的行为,建议的做法是设置客户端属性ContentEditable=false,参考

显然,即使禁用了几个控件的视图状态,该页面的行为也是有状态的。原因在于该页面使用了两个服务器控件:TextBox和CheckBox,它们的关键属性(Text和Checked)根据用户设置的值进行更新。对于这些属性,投递的值将覆盖视图状态可能已经设置的任何设置。因而,如果只对持久地存储这些属性感兴趣,则根本不需要视图状态。

SYSK 118: ReadOnly or ContentEditable?

同样,.aspx文件中设计时设置的所有控件属性以及在会话期间不会发生变化的所有控件属性,不需要启用视图状态。如下代码说明了这一点:

 

<asp:textbox runat=”server” id=”TextBox1″ Text=”Some text”

SYSK 118: ReadOnly or ContentEditable?
Consider this:  you want a text box on a web page to be not editable by the user, but you want to be able to change the text box’s contents in client side script and see the updated text on the server.

MaxLength=”20″ ReadOnly=”true” />

 

我们不需要用视图状态来使TextBox的Text属性保持最新;只要这些属性在页面的生命期会改变其值,如ReadOnly或MaxLength属性,就不需要使用视图状态来更新它们。如果这两个属性在页面生命期内保持不变,也不需要对它们启用视图状态。

Did you know that if you set TextBox1.ReadOnly = true, the value set by the client side script will not be visible on the server?    Try it for yourself… Here is the code:

那么,什么时候真正需要视图状态呢?

 

每当页面要求在页面生命期内更新附属控件的属性(不受投递的值支配),就需要视图状态。在这种情况下,“已更新的(updated)”表示原始值发生变化——要么是默认值,要么是设计时赋给该属性的值。考虑如下窗体:

<form id=”form1″ runat=”server”>

<script runat=”server”>

    <div>

void Page_Load(object sender, EventArgs e)

        <input id=”Button2″ type=”button” value=”Change Text via Client-Side Script” onclick=”ChangeText();” />

{

    </div>

if (!IsPostBack)

    <asp:TextBox ID=”TextBox1″ runat=”server”>initial text</asp:TextBox>

theInput.ReadOnly = true;

    <asp:Button ID=”Button1″ runat=”server” OnClick=”Button1_Click” Text=”See Value on the Server-Side” />

}

</form>

</script>

 

<form id=”form1″ runat=”server”>

<script language=”javascript” type=”text/javascript”>

<asp:textbox runat=”server” id=”theInput” text=”Am I read-only?”
/>

<!–

<asp:button ID=”Button1″ runat=”server” text=”Click” onclick=”OnPost”
/>

function ChangeText()

</form>

{    

第一次加载该页面时,文本框是只读的。接着,单击该按钮以回发页面。如果视图状态被启用,则页面如期望的那样起作用,并且文本框保持只读。如果禁用该文本框的视图状态,则恢复ReadOnly属性的原始设置——这里为false。

    form1[“TextBox1”].setAttribute(“innerText”, “abc”);

一般而言,只要状态信息可以从客户端或运行时环境中推断出,就不需要视图状态。相反,如果状态信息不能动态地推断出,并且不能保证页面回发时正确恢复所有属性,则必须启用视图状态。这正好是视图状态以下载和上传额外的字节为代价能做到的。要节省那些字节,就必须提供一种替代方法。

}    

提示

通过使用布尔属性EnableViewState,可以以编程的方式启用和禁用页面及其各控件的视图状态。

–>    

禁用视图状态也会提出一些难于诊断和修复的更微妙的问题,尤其在使用第三方控件或者可以访问源代码的控件时。实际上,一些ASP.NET控件不仅可以把编程接口的官方属性保存到视图状态中,而且还可以把内部属性以及标记为保护的(甚至是私有的)行为属性保存到视图状态中。不幸的是,对于这些控件,没有禁用视图状态的选项。但是ASP.NET
2.0用控件状态(control state)克服了这一缺陷。

</script>

 

 

我们可以做个实验,在Button1_Click事件中,编写代码:

 

ListBox.Items.Add(”客户端点击按钮一次!”);

public partial class MyForm : System.Web.UI.Page

此时运行该应用程序,单击网页上的按钮,在ListBox中会添加内容,不断地单击,内容则不断添加。如果我们将ListBox的EnableViewState属性改为false时,不断单击按钮,则只能添加一次。

{

这样有什么好处呢?如果我们在开发Web应用程序时,某些控件是不需要接受用户的操作或只需要接受一次操作的时候,我们可以将这些控件的EnableViewState属性改为false,这样可以优化我们的程序,提高网络访问的速度。

    protected void Page_Load(object sender, EventArgs e)

    {            

        TextBox1.ReadOnly = true;

    }

 

    protected void Button1_Click(object sender, EventArgs e)

    {

        Response.Write(TextBox1.Text + “<br>”);

        

    }

}

 

However, if instead of setting TextBox1.ReadOnly property you set ContentEditable attribute to false, you’ll get the behavior you’re looking for:

TextBox1.Attributes[“contentEditable”] = “false”;

 

 

Special thanks to Vinay Kumar Baliyan who replied with the information used in this post to Les Cardinal‘s question.

其实如果是设置客户端属性的话,设置客户端的readonly属性应该也是可以的:

TextBox1.Attributes[“readonly”] = “true”;

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2020 大奖888网页版登陆 版权所有