【问题标题】:Viewstate and controls in ASP.NETASP.NET 中的视图状态和控件
【发布时间】:2012-02-01 16:26:54
【问题描述】:

几天前我发布了一个关于视图状态的问题,经过一些测试后,我得出了一些结论/结果。基于这些结果,我对某人将如何做某些事情有几个问题。

这是我运行的测试结果:

  1. 如果 usercontrolA 从页面的OnInit 加载,那么他的视图状态将在OnLoad 中可用。 usercontrolA 从其 OnInit 加载的所有其他控件都将在其 OnLoad 中准备好其视图状态。
  2. 如果 usercontrolA 从页面的OnLoad 加载,那么他的视图状态将在OnPreRender 中可用。 usercontrolA 从其 OnLoad 加载的所有其他控件将在其 OnPreRender 中提供其视图状态。
  3. 如果从页面的事件(例如:按钮单击。事件在OnLoadOnPreRender 之前触发)加载用户控件A,则其视图状态将不可用。 usercontrolA 加载的所有其他控件的视图状态都将不可用。

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

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

感谢任何建议和/或链接。

【问题讨论】:

    标签: c# asp.net user-controls viewstate


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      在 OnInit 中加载动态控件是公认的做法,以便它们获得完整的控件生命周期。不过,我不确定我是否特别了解您的情况-如果您正在加载基于按钮单击的控件,那么为什么此时它会有视图状态?在next 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 属性。文本框类似。因此,根据我的阅读,应该可以随时添加,然后访问 ViewState。不过,这似乎与我的经验并不相符,因此似乎有必要进行进一步调查。

      【讨论】:

      • 嗨,这是我尝试使用视图状态的问题之一。我需要以某种方式标记我的控件需要在上一个回发上由 onclick 处理程序加载后在下一次回发上加载。我正在考虑使用页面中具有值的视图状态。在我的测试中,这似乎是要走的路。
      【解决方案3】:

      我很惊讶,但对您的结果很感兴趣。当我使用动态控件时,我总是将它们添加到Page_Init。别的什么都行不通。但你是对的 - 如果你添加它们以响应按钮点击,你会怎么做。

      我发现的唯一方法是检查PageInitRequest.Form("__EVENTTARGET") 集合。这包含触发回发的控件的控件 ID,例如按钮单击。它当然会受到它出现的命名容器的限制。一旦你通过这种方法识别了“事件”,你就可以添加你想要的控件。

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

      有趣的是,ViewStatePreRender 上可用,如果您在Page_Load 添加控件。但正如上面的链接所表明的那样,现在帮助你为时已晚。控制状态在负载循环期间再水化。如果它不存在,那么您的控件状态或动态控件就会消失。

      【讨论】:

      • 我认为他未能区分 Viewstate 可用和在回发之间保持不变。 Viewstate 在 Page.Load 期间从以前的回发中加载,这意味着如果您在 Page.Load 处理程序期间创建控件,它将失去其 viewstate 自动持久化的机会。
      【解决方案4】:

      您是否尝试使用LoadComplete 事件?

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

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

      【讨论】:

      • 感谢您的回复,但我不确定我是否在关注。其中一个用户控件需要从其视图状态中获取一个值。 LoadComplete 位于页面级别。
      • 如果您想要一个知道发生了哪些点击事件的事件,LoadComplete 是第一个。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 1970-01-01
      • 1970-01-01
      • 2012-04-19
      • 2013-07-16
      • 2013-03-30
      相关资源
      最近更新 更多