C# ASP.NET中的Viewstate和控件
几天前我发布了一个关于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
OnInit
加载的,则他的视图状态将在OnLoad
中可用。usercontrolA从其OnInit
加载的所有其他控件将在其OnLoad
中准备好视图状态OnLoad
加载usercontrolA,则其视图状态将在OnPreRender
中可用。usercontrolA从其OnLoad
加载的所有其他控件将在其OnPreRender
中提供其视图状态OnLoad
之后和OnPreRender
之前触发),则其viewstate将不可用。usercontrolA加载的所有其他控件的viewstate将不可用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,它将包含这些值。在我的测试中,这似乎是一条可行之路。