【问题标题】:Why label's value is changed?为什么标签的值会改变?
【发布时间】:2016-11-10 11:38:32
【问题描述】:

我知道即使为 TextBox 禁用了 ViewState,我们也不会丢失数据,因为它实现了 IPostBackDataHandler 接口。

<asp:TextBox ID="TextBox1" runat="server" EnableViewState="False"/>

但我的问题是为什么标签也会发生这种情况?为什么标签没有实现IPostBackDataHandler 接口,即使禁用了 ViewState 也不会丢失数据?

<asp:Label ID="Label1" runat="server" EnableViewState="False" ViewStateMode="Disabled"/>

文本框定义:

public class TextBox : WebControl, IPostBackDataHandler,

标签定义:

public class Label : WebControl, ITextControl

我的代码:

<form id="form1" runat="server">
<div>
    <asp:Label ID="Label1" runat="server" EnableViewState="False" ViewStateMode="Disabled" Text="Before click"></asp:Label>
    <asp:TextBox ID="TextBox1" runat="server" EnableViewState="False"></asp:TextBox>
    <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_OnClick"/>
</div>
</form>

以及后面的代码:

protected void Button1_OnClick(object sender, EventArgs e)
{
    Label1.Text = "Changed.";
}

单击按钮后,我希望在标签中看到“单击前”,但单击按钮后,我在标签中看到了“已更改”文本。

【问题讨论】:

  • 什么叫“数据”?标签和文本框上的文本?如果是这样,这个文本是如何在标记中设置的?
  • @Andrei 在按钮上单击我写了这个 TextBox1.Text = "Changed"; Label1.Text = "已更改。";我希望标签会丢失它的数据,因为我禁用了视图状态并且它没有实现 IPostBackDataHandler。
  • 好的,很清楚你所说的数据是什么意思,但不是你所说的“失败”。因此,您在单击时更改文本。现在你期待什么?页面加载并且控件具有“已更改”以外的值?或者下一次回发发生并且控制具有“已更改”以外的值?
  • @Andrei EnableViewState="False" 有什么用?不应该通过禁用它在回发后丢失更改的数据吗?很清楚为什么 EnableViewState="False" 不适用于 Textbox,但我想知道为什么它也不适用于标签?
  • 标签上的文字是什么?

标签: c# asp.net


【解决方案1】:

好的,我删除了我之前的答案,我会尝试用一个例子重新说明它。

首先,正如其他人所说,ViewState 的想法是保持回发之间的状态,而不是在单个页面加载周期中,所以您看到的是预期的行为。

要通过示例查看差异,请尝试使用 2 个按钮添加标签:

 <asp:Label ID="Label1" runat="server" EnableViewState="False" Text="Before click"></asp:Label>  
 <asp:Button ID="btn1" Text="Click" OnClick="btn1_Click" runat="server" />
 <asp:Button ID="btnReset" Text="Reset" OnClick="btnReset_Click" runat="server" />

btn1 将值设置为“已更改”,btnReset 有一个空处理程序。

现在将EnableViewState 设置为False,如果您点击btn1,页面会重新加载,btn1_Click 会执行,并且如果您点击@987654329,页面将使用标签值=“已更改”呈现@ 页面将再次重新加载,但由于视图状态被禁用,标签将恢复为原始文本“点击前”

如果您在标签上将EnableViewState 设置为True 并单击btn1 然后btnReset,标签值将保持为“已更改”,因为在回发期间会保留该状态

希望能澄清一点

【讨论】:

  • 那么你是想说在点击 btn1 和内部 btn1_Click 之后设置标签的值是在回发发生之后?对吗?
  • 而且在我更改了文本之后,在浏览器中呈现的结果称为 Response 还是什么?
  • 按钮处理程序在 during 回发期间执行 .. 在浏览器中呈现的是服务器发送的 HTTP 响应的一部分 是的 .. 你可能想看看如果您不熟悉 ASP.NET 页面生命周期,请点击此处stackoverflow.com/questions/8457297/… 的答案
【解决方案2】:

这将是冗长而详细的。

让我们从这个标记开始。几乎和你的一样,多了一个按钮和一个标签。稍后我会解释为什么我们需要它们。

<form id="form1" runat="server">
<div>
    <asp:Label ID="Label1" runat="server" EnableViewState="False" ViewStateMode="Disabled" Text="Before click"></asp:Label>
    <asp:TextBox ID="TextBox1" runat="server" EnableViewState="False"></asp:TextBox>
    <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_OnClick"/>

    <asp:Label ID="Label2" runat="server" Text="Blah" />
    <asp:Button ID="Button2" runat="server" Text="Button" OnClick="Button2_OnClick"/>
</div>
</form>

我们将在后面使用此代码。同样,我稍后会解释第二个处理程序的用途:

protected void Button1_OnClick(object sender, EventArgs e)
{
    Label1.Text = "Changed";
}

protected void Button2_OnClick(object sender, EventArgs e)
{
    Label2.Text = Label1.Text;
}

让我们看看当我们最初加载页面时会发生什么。首先 ASP.NET 读取所有标记,然后遍历所有事件的页面生命周期。在标记解析阶段Label1 获得分配的文本Before click,并且在初始加载期间以后永远不会更改。所以稍后在渲染阶段,这就是渲染成 HTML 并发送到浏览器的内容。因此Before click 显示在屏幕上。很好很容易。

现在我们点击Button1。回发发生,该术语描述了在最初加载后由其控件之一发送到同一页面的请求。同样,一切都从 ASP.NET 解析标记开始,Label1 再次获得分配的文本 Before click。但是随后会发生页面生命周期事件,包括控制事件处理程序。在Button1 的处理程序中,Label1 的文本更改为Changed。现在需要注意的重要一点是:如果启用了 Label1 的 ViewState,则该新值将存储在那里,并且将为属性 Label1.Text 启用所谓的跟踪。但是 ViewState 被禁用,因此新值不会存储在除Label1 之外的任何地方。接下来是渲染页面阶段,由于Label1.Text 仍然拥有Changed 的值,这就是渲染成HTML 并发送到浏览器显示的内容。但请注意,此新值不会在 ViewState 字段内发送。如您所见,是否启用 ViewState 对回发后显示的内容没有任何影响。

现在我们将单击Button2,这将触发另一个回发。同样,ASP.NET 解析标记,Label1 再次获取文本 Before click。然后是 ViewState 加载部分。如果启用了 Label1.Text 的 ViewState,它会将更改的值加载到此属性中。但是 ViewState 被禁用,因此值保持不变。因此,当我们到达Button2点击处理程序时,Label1.Text的值仍然是Before click,它被分配给Label2.Text。但是Label2 启用了 ViewState,因此其文本的新值存储在 ViewState 中并发送到客户端(ViewState 在客户端实现为隐藏字段)。当一切都到达浏览器时,我们可以看到Label1Label2 都显示Before click

为了确定这一点,我们将进行第三次回发,现在再次单击Button1。就像第一次回发一样,Label1Changed 文本结束。但是Label2 呢?好吧,这个启用了 ViewState,所以在初始标记解析期间,ASP.NET 为其分配值Blah,并在加载 ViewState 期间用Before click 替换此值。在页面生命周期中没有其他因素影响这个值(我们这次没有点击 Button2),所以我们最终会在浏览器中看到 ChangedBefore click

希望它能明确 ViewState 的用途以及禁用它的作用。如果您想更深入地了解 ViewState 的工作原理,我强烈推荐这篇文章:TRULY Understanding ViewState

【讨论】:

    【解决方案3】:

    我认为您对 ViewState 的理解有误。

    ViewState 中的数据存储在请求之间,而不是在页面生命周期中。 BTW - 在 SaveStateComplete 事件中的 PreRenderComplete 事件之后生成 ViewState 数据。

    https://msdn.microsoft.com/en-us/library/ms178472.aspx

    如果您关闭了 ViewState - 请认为它不会在输出中生成。

    在页面生命周期中,分配给控件(以及页面字段和属性,因为页面只是一个类)的所有数据都将按照您在 aspx 中定义的方式呈现。但是之后会丢失,除非保存在ViewState中。

    【讨论】:

    • 感谢您的回答。但我的问题是为什么 EnableViewState=false 不适用于标签。
    • @user5032790 标签按预期工作,您的预期是错误的。您是否确切地知道 View-state 的作用是什么,以及当您禁用它时究竟是什么不起作用?
    • @Maarten 当我在点击时更改标签的文本时,它会触发回发,并且由于我禁用了标签上的视图状态,因此更改的文本应该消失了。这不是预期的行为吗?另外请告诉我按钮点击不是回发吗?
    • @user5032790:标签的文本由回发更改。它不会更改文本然后回发。单击发生在服务器端,因此事件过程大致是 1)您单击按钮 2)浏览器向服务器发出请求 3)服务器处理请求,包括按钮单击。正是在这里,标签被改变了。 4)服务器将新页面发送回浏览器,包括您更新的标签值。
    • @user5032790 视图状态使控件能够在回发期间保存其当前状态。这意味着如果您有一个带有在代码中设置的值的标签,并且已完成回发,则该值来自代码将在回发期间保留。如果禁用视图状态,则不会保留该值。现在,以你的例子为例。如果您在回发期间执行的事件处理程序中设置标签的值,那么当然会显示该值,因为 那个 值与回发没有任何关系。
    猜你喜欢
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-18
    • 1970-01-01
    • 2016-06-20
    • 1970-01-01
    • 2011-11-21
    相关资源
    最近更新 更多