ASP.NET中的Viewstate和控件

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

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

  1. 如果从页面的OnInit加载usercontrolA,那么他的视图状态将在OnLoad可用。 usercontrolA从其OnInit加载的所有其他控件将在其OnLoad准备好其viewstate。
  2. 如果从Page的OnLoad加载usercontrolA,那么他的视图状态将在OnPreRender可用。 usercontrolA从其OnLoad加载的所有其他控件将在其OnPreRender提供其视图状态。
  3. 如果usercontrolA是从一个事件加载的(例如:按钮点击。事件在OnLoad之后和OnPreRender之前触发),那么他的视图状态将不可用。 usercontrolA loades的所有其他控件都不会提供其viewstate。

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

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

任何建议和/或链接表示赞赏。

在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; } } 

然而,稍微有趣一点的是,根据追赶事件 – 它确实无关紧要。 用于动态加载控件的callstack类似于:

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

Label为例,它会覆盖LoadViewState并直接从ViewState中提取它的Text属性。 TextBox类似。 因此,通过我的阅读,可以随时添加,然后访问ViewState。 但是,根据我的经验,这似乎并不合适,因此需要进一步调查。

我不认为我可以添加本文未涵盖的任何内容。

请特别注意生命周期事件部分。

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

我很惊讶但对你的结果很感兴趣。 当我使用动态控件时,我总是在Page_Init添加它们。 其他任何东西都不起作用。 但你是对的 – 如果你是为了响应按钮点击而添加它们,你会怎么做?

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

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

有趣的是,如果在Page_Load添加控件, ViewState可在PreRender使用。 但是,由于上面的链接表明它来不及帮助你。 控制状态在加载循环期间被再水合。 如果不存在那么你的控制状态或动态控制就会消失。

您是否尝试使用LoadComplete事件?

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

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