查看ASP.NET中的状态和控件

本文关键字:状态 控件 ASP NET 查看 | 更新日期: 2023-09-27 18:22:04

几天前我发布了一个关于viewstate的问题,在运行了一些测试后,我得出了一些结论/结果。根据这些结果,我有几个问题,关于某人将如何做某些事情。

以下是我运行的测试结果:

  1. 如果从页面的OnInit加载usercontrolA,则他的视图状态将在OnLoad中可用。usercontrolA从其OnInit加载的所有其他控件的视图状态都将在其OnLoad中就绪
  2. 如果从页面的OnLoad加载usercontrolA,那么他的视图状态将在OnPreRender中可用。usercontrolA从其OnLoad加载的所有其他控件的视图状态都将在其OnPreRender中可用
  3. 如果从页面的事件(例如:按钮点击。事件在OnLoad之后和OnPreRender之前触发)加载usercontrolA,则他的视图状态将不可用。usercontrolA加载的所有其他控件的视图状态都不可用

因此,在一个完美的世界中,您总是使用情形#1加载所有控件,以便它们的视图状态在其OnLoad上可用。不幸的是,当您需要从按钮单击或从OnLoad加载控件时,控件是否无法在OnPreRender阶段之前获得其视图状态?

我读了很多关于viewstate的文章,认为我理解它,但在我当前加载用户控件和加载其他用户控件的应用程序上工作时,我很难在我的叶子(链中的最后一个)用户控件上获得viewstate。

欢迎提供任何建议和/或链接。

查看ASP.NET中的状态和控件

我认为我不能添加本文没有涉及的任何内容。

请特别查看生命周期事件部分。

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

在OnInit中加载动态控件是公认的做法,这样它们就可以获得完整的控制生命周期。不过,我不确定我是否特别理解你的情况——如果你是基于按钮点击加载控件,为什么它会在此时具有视图状态?在下一个OnInit上,您应该再次加载控件(我通常使用页面级Viewstate项来跟踪需要加载的特定控件),以便它可以从Viewstate还原。类似于:

class Default : Page {
   enum LoadedControl { Textbox, Label, GridView }
   override OnInit() {
      if (IsPostback) {
        var c = Viewstate["LoadedControl"] as LoadedControl;
        if (c != null) LoadDynamicControl(c);
      }
   }
   void Button_Click() {
     var c = (LoadedControl)Enum.Parse(typeof(LoadedControl), ddl.SelectedValue);
     LoadDynamicControl(c);
   }
   void LoadDynamicControl(LoadedControl c) {
     switch (c) {
        case LoadedControl.Textbox:
           this.ph.Controls.Add(new Textbox());
           break;
        ...
     }
     ViewState["LoadedControl"] = c;
   }
}

不过,更有趣的一点是,根据追赶事件,这真的不重要。用于动态加载控件的调用堆栈看起来像:

Control.Controls.Add(Control)
   Control.AddedControl(Control)
      Control.LoadViewStateRecursive(object)
          Control.LoadViewState(object)

Label为例,它覆盖LoadViewState,并直接从ViewState中提取其Text属性。TextBox与此类似。因此,根据我的阅读,应该可以在任何时候添加,然后访问ViewState。不过,这似乎与我的经历不符,所以进一步的调查似乎是有必要的。

我很惊讶,但对您的结果很感兴趣。当我使用动态控件时,我总是将它们添加到Page_Init中。其他任何东西都不起作用。但你是对的——如果你是在点击按钮时添加它们,你该怎么做呢。

我找到的唯一方法是在PageInit上检查Request.Form("__EVENTTARGET")集合。它包含触发回发的控件的控件ID,例如单击按钮。当然,它将由它出现的命名容器限定。一旦你用这种方法识别了"事件",你就可以添加你想要的控件。

这当然有点古怪,但这是我做这些事情的唯一方法。它确实有效。

有趣的是,如果在Page_Load添加控件,ViewStatePreRender上可用。但正如上面的链接所表明的那样,现在帮助你已经太晚了。控件状态在加载循环期间重新水合。如果它不在那里,那么你的控制状态或动态控制就会消失。

您是否尝试使用LoadComplete事件?

将此事件用于需要加载页面上所有其他控件的任务。

这是在PageLoad和所有事件(ButtonClick等)之后触发的,因此您的UserControls加载在Button Click事件中,并且在LoadComplete中它们的ViewState已经初始化。