C# ASP.NET中的Viewstate和控件

C# ASP.NET中的Viewstate和控件,c#,asp.net,user-controls,viewstate,C#,Asp.net,User Controls,Viewstate,几天前我发布了一个关于viewstate的问题,在运行了一些测试之后,我得出了一些结论/结果。基于这些结果,我有几个问题,关于某人将如何做某些事情 以下是我运行的测试结果: 如果usercontrolA是从页面的OnInit加载的,则他的视图状态将在OnLoad中可用。usercontrolA从其OnInit加载的所有其他控件将在其OnLoad中准备好视图状态 如果从页面的OnLoad加载usercontrolA,则其视图状态将在OnPreRender中可用。usercontrolA从其OnLo

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

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

  • 如果usercontrolA是从页面的
    OnInit
    加载的,则他的视图状态将在
    OnLoad
    中可用。usercontrolA从其
    OnInit
    加载的所有其他控件将在其
    OnLoad
    中准备好视图状态
  • 如果从页面的
    OnLoad
    加载usercontrolA,则其视图状态将在
    OnPreRender
    中可用。usercontrolA从其
    OnLoad
    加载的所有其他控件将在其
    OnPreRender
    中提供其视图状态
  • 如果从事件加载usercontrolA(例如:按钮单击。事件在页面的
    OnLoad
    之后和
    OnPreRender
    之前触发),则其viewstate将不可用。usercontrolA加载的所有其他控件的viewstate将不可用
  • 因此,在一个完美的世界中,您总是使用情境#1加载所有控件,以便它们的视图状态在其
    OnLoad
    上可用。不幸的是,当您需要从按钮单击或从
    OnLoad
    加载控件时,控件是否无法在
    OnPreRender
    阶段之前获取其视图状态

    我读了很多关于viewstate的文章,认为我理解了它,但是在我当前的应用程序中加载了usercontrols,加载了其他usercontrols,我很难在我的叶(链中的最后一个)usercontrols上获取viewstate


    任何建议和/或链接都将不胜感激。

    我认为我无法添加本文未涵盖的内容

    具体查看生命周期事件部分


    我对你的结果感到惊讶但很感兴趣。当我使用动态控件时,我总是将它们添加到
    Page\u Init
    。其他的都不行。但是你是对的——如果你是为了响应按钮点击而添加它们,你该怎么做呢

    我找到的唯一方法是在
    PageInit
    上检查
    Request.Form(“\uu EVENTTARGET”)
    集合。它包含触发回发的控件的控件ID,例如单击按钮。当然,它将由它出现在其中的命名容器限定。通过此方法识别“事件”后,可以添加所需的控件

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


    有趣的是,如果在
    Page\u Load
    添加控件,则
    ViewState
    PreRender
    上可用。但正如上面的链接所显示的那样,现在帮助你已经太晚了。控制状态在负载循环期间重新水化。如果没有,则控件状态或动态控件将消失。

    是否尝试使用
    LoadComplete
    事件

    对于需要加载页面上所有其他控件的任务,请使用此事件


    这是在
    PageLoad
    和所有事件(ButtonClick等)之后触发的,因此您的用户控件将加载到ButtonClick事件中,并且在
    LoadComplete
    中,它们的视图状态已经初始化。

    在OnInit中加载动态控件是公认的做法,以便它们获得完整的控件生命周期。但我不确定我是否特别了解您的情况-如果您正在加载基于按钮单击的控件,为什么此时会有viewstate?在下一个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)
    
    不过,更有趣的一点是,根据追赶事件,这真的不重要。用于动态加载控件的调用堆栈如下所示:

    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都应该是可以的。不过,这似乎与我的经验不符,因此进一步的调查似乎是有必要的。

    我认为他未能区分Viewstate是否可用以及是否在回发之间持久化。Viewstate是在Page.Load期间从以前的回发中加载的,这意味着如果您在Page.Load处理程序期间创建控件,它将无法自动保持其Viewstate。感谢您的响应,但我不确定是否遵循了。其中一个UserControl需要从其viewstate获取值。LoadComplete位于页面级别。如果您想要知道发生了哪些单击事件的事件,LoadComplete是第一个。您好,这是我尝试使用viewstate的原因之一。我需要在上一次回发中的onclick处理程序加载控件后,以某种方式标记我的控件需要在下一次回发中加载。我正在考虑使用页面中的viewstate,它将包含这些值。在我的测试中,这似乎是一条可行之路。