65.9K
CodeProject 正在变化。 阅读更多。
Home

初学者教程 - 理解 ASP.NET 中的 ControlState

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.76/5 (16投票s)

2012年2月17日

CPOL

3分钟阅读

viewsIcon

73694

downloadIcon

881

初学者教程 - 理解 ASP.NET 中的 ControlState

引言

本文旨在理解为什么以及何时我们需要使用 ControlState 进行状态管理。我们还会通过一个非常基础的 ControlState 实现来尝试理解这一点。

背景

默认情况下,ASP.NET 页面具有 EnableViewState 属性,值为 true。这使得 ASP.NET 自动跟踪页面上所有控件的状态。现在,如果我正在处理一个 Web 页面,我知道所有控件都将在每次回发时动态绑定到一些数据,我就不必跟踪控件的旧信息。所以我可能决定关闭它。这对于页面开发人员来说是一个很好的选择,但如果同一页面包含自定义控件,并且该自定义控件使用 ViewState 来管理控件内的数据,情况可能会变得混乱。

这里的重点是从控件开发人员的角度来看。我如何编写不受控件用户操作影响的控件,也就是说,无论 ASP.NET 是否启用 ViewState,它都将起作用。

Using the Code

ASP.NET 已经为此类场景提供了一种机制,称为 ControlState。在这里,我们将尝试看看如何编写具有适当的 ControlStateViewState 管理的自定义控件的正确方法。

假设我们有一个非常简单的自定义控件,它向用户显示几条欢迎消息。如果我去创建一个自定义控件项目来实现这一点,我将得到类似的东西

[ToolboxData("<{0}:WebCustomControl runat="server"></{0}:WebCustomControl>")]
public class WebCustomControl : WebControl
{
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("")]
    [Localizable(true)]
    public string Text
    {
        get
        {
            String s = (String)ViewState["Text"];
            return ((s == null) ? String.Empty : s);
        }

        set
        {
            ViewState["Text"] = value;
        }
    }

    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("")]
    [Localizable(true)]
    public string Text2
    {
        get
        {
            String s = (String)ViewState["Text2"];
            return ((s == null) ? String.Empty : s);
        }

        set
        {
            ViewState["Text2"] = value;
        }
    }

    protected override void RenderContents(HtmlTextWriter output)
    {
        output.Write(Text);
        output.Write("<br/>");
        output.Write(Text2);
        output.Write("<br/>");
    }       
}

一个非常基本的控件,它呈现两条欢迎消息,控件的用户可以选择从外部设置这些消息,这可能来自数据库调用或从文件中读取。用户可能只做一次,并希望我们的控件记住这些 strings。所以,假设控件的用户正在做类似的事情

if (IsPostBack == false)
{
    WebCustomControl_1.Text = "This is a dummy Text";
    WebCustomControl_1.Text2 = "This is another dummy Text";
}

现在,对于第一次运行,他将进行属性设置,从下一次开始,他将其留给控件来呈现这些内容。现在,页面仍然将 EnableViewState 属性设置为 "true"。因此,如果我们在页面上运行并进行回发,我们将观察到预期的行为。让我们看看用户将看到什么

Sample Image - control state snapshot

现在,如果用户禁用了页面的 viewstate,甚至禁用了我们自定义控件的 viewstate,当发生回发时

Sample Image - control state snapshot

这些值消失了,原因是我们的控件依赖于 ViewState 才能运行,我们需要将这种依赖关系转移到 controlState,以便即使在这种情况下,我们的控件也能继续工作。

因此,让我们使用 Control State 来处理一行文本,而不是其他文本(纯粹是为了看看这些东西有何不同,我们可以在同一段代码中比较正确的方法和错误的方法,理想情况下,所有控件信息都应该使用 ControlState 机制)。

我们在这里需要做的是,我们必须重写 OnInit 方法并在初始化期间调用 RegisterRequiresControlState 方法。然后,我们必须重写 SaveControlStateLoadControlState 方法。因此,让我们看看我们如何使用 ControlState 处理我们控件的 Text 属性。

protected override void OnInit(EventArgs e)
{
    Page.RegisterRequiresControlState(this);
    base.OnInit(e);
}

protected override void LoadControlState(object savedState)
{
    Text = (string)savedState;
}

protected override object SaveControlState()
{
    return Text;
}

现在,我们已经使用 controlState 处理了控件的第一个属性,第二个属性未使用它。现在,在回发时,输出是

Sample Image - control state snapshot

查看代码以查看差异。正确的方法是 ControlState 用于第一个属性的方式,它应该用于自定义控件中的所有控件。

关注点

总而言之,我们看到了什么是控件状态以及如何在自定义控件中启用它。控件状态消除了开发人员是否使用 ViewState 的决定。每当我们想使用控件状态时,您应该考虑是实现它,还是将如何保存状态信息的决定交给使用您控件的开发人员。第二个选择更可取,因为它减少了对 Page 可以设置的内容的依赖。

历史

  • 2012 年 2 月 17 日:关于 ControlState 的解释性教程
© . All rights reserved.