I posted a question a couple of days ago about viewstate and after running some tests I have come to some conclusions/results. Based on these results I have a few questions as to how someone would do certain things.
我几天前发布了一个关于viewstate的问题,经过一些测试后,我得出了一些结论/结果。基于这些结果,我有一些关于某人如何做某些事情的问题。
Here are the results of my tests that I ran:
以下是我运行的测试结果:
- If usercontrolA is loaded from
OnInit
of a Page, then his viewstate will be available inOnLoad
. All other controls that usercontrolA loads from it'sOnInit
, will have their viewstate ready in theirOnLoad
. - If usercontrolA is loaded from
OnLoad
of a Page, then his viewstate will be available inOnPreRender
. All other controls that usercontrolA loads from it'sOnLoad
, will have their viewstate available in theirOnPreRender
. - If usercontrolA is loaded from an event (Example: button click. Events fire after
OnLoad
and beforeOnPreRender
) of a Page, then his viewstate will not be available. All other controls that usercontrolA loades will not have their viewstate available.
如果从页面的OnInit加载usercontrolA,那么他的视图状态将在OnLoad中可用。 usercontrolA从其OnInit加载的所有其他控件将在其OnLoad中准备好其viewstate。
如果从Page的OnLoad加载usercontrolA,那么他的视图状态将在OnPreRender中可用。 usercontrolA从其OnLoad加载的所有其他控件将在其OnPreRender中提供其视图状态。
如果usercontrolA是从一个事件加载的(例如:按钮点击。事件在OnLoad之后和OnPreRender之前触发),那么他的视图状态将不可用。 usercontrolA loades的所有其他控件都不会提供其viewstate。
So in a perfect world you would always load all controls using situation #1, so that their viewstate is available on their OnLoad
. Unfortunately when you need to load a control from a button click or from a OnLoad
, is there no way for control to get its viewstate before OnPreRender
stage?
因此,在一个完美的世界中,您总是会使用情境#1加载所有控件,以便他们的视图状态可以在他们的OnLoad上使用。不幸的是,当您需要从按钮单击或OnLoad加载控件时,是否无法控制在OnPreRender阶段之前获取其视图状态?
I have read a bunch of articles on viewstate and thought I understood it, but working on my current application which loads usercontrols which load other usercontrols, I am having a real hard time with being able to get viewstate on my leaf (last in the chain) usercontrol.
我已经阅读了一堆关于viewstate的文章,并且认为我理解它,但是在我当前的应用程序上加载加载其他用户控件的usercontrols,我真的很难在我的叶子上获得viewstate(最后在链中) )usercontrol。
Any suggestions and/or links are appreciated.
任何建议和/或链接表示赞赏。
4 个解决方案
#1
3
It is accepted practice to load dynamic controls in OnInit, so that they get the full control lifecycle. I'm not sure I particularly understand your situation though - if you're loading a control based on a button click, why would it have viewstate at that point? On the next OnInit, you should load the control again (I usually use a page level Viewstate item to track that a particular control needs to be loaded) so that it can restore from Viewstate. Something like:
在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;
}
}
The slightly more interesting bit, though, is that according to catch-up events - it really shouldn't matter. The callstack for dynamically loading a control looks something like:
然而,稍微有趣一点的是,根据追赶事件 - 它确实无关紧要。用于动态加载控件的callstack类似于:
Control.Controls.Add(Control)
Control.AddedControl(Control)
Control.LoadViewStateRecursive(object)
Control.LoadViewState(object)
Taking Label
as an example, it overrides LoadViewState
and pulls it's Text
property directly from ViewState. TextBox is similar. So, by my reading, it should be OK to add at any point, and then access ViewState. That doesn't seem to be jive with my experience, though, so further investigation seems warranted.
以Label为例,它会覆盖LoadViewState并直接从ViewState中提取它的Text属性。 TextBox类似。因此,通过我的阅读,可以随时添加,然后访问ViewState。但是,根据我的经验,这似乎并不合适,因此需要进一步调查。
#2
4
I don't think I can add anything that this article doesn't cover.
我不认为我可以添加本文未涵盖的任何内容。
Look specifically at the Life Cycle Events section.
请特别注意生命周期事件部分。
#3
1
I'm surprised but interested about your results. When I work with dynamic controls I always add them in Page_Init
. Anything else doesn't work. But you are right - how do you do it if you are adding them in response to a button click.
我很惊讶但对你的结果很感兴趣。当我使用动态控件时,我总是在Page_Init中添加它们。其他任何东西都不起作用。但你是对的 - 如果你是为了响应按钮点击而添加它们,你会怎么做?
The only way I have found is by examining Request.Form("__EVENTTARGET")
collection at PageInit
. This contains the control ID of the control that has triggered the postback so for instance a button click. It will of course be qualified by the naming containers it appears in. Once you have identified the 'event' by this method you can add the controls you want.
我找到的唯一方法是在PageInit上检查Request.Form(“__ EVENTTARGET”)集合。这包含触发回发的控件的控件ID,例如按钮单击。它当然会被它出现的命名容器限定。一旦你通过这种方法识别出'event',就可以添加你想要的控件。
It is of course all a bit hacky but it's the only way I found of doing these things. It does work.
它当然有点hacky但它是我发现做这些事情的唯一方法。它确实有效。
It's interesting that the ViewState
is available on PreRender
if you add the controls at Page_Load
. But as the above link indicates it too late to help you then. The controls state is rehydrated during the load cycle. If it's not there then your control state or dynamic controls are just going to disappear.
有趣的是,如果在Page_Load中添加控件,ViewState可在PreRender上使用。但是,由于上面的链接表明它来不及帮助你。控制状态在加载循环期间被再水合。如果不存在那么你的控制状态或动态控制就会消失。
#4
0
Did you try to use LoadComplete
event?
您是否尝试使用LoadComplete事件?
Use this event for tasks that require that all other controls on the page be loaded.
将此事件用于需要加载页面上所有其他控件的任务。
This is fired after PageLoad
and all events (ButtonClick, etc.), so your UserControls are are loaded in ButtonClick events, and in LoadComplete
their ViewState is already initialized.
这是在PageLoad和所有事件(ButtonClick等)之后触发的,因此您的UserControls在ButtonClick事件中加载,而在LoadComplete中,它们的ViewState已经初始化。
#1
3
It is accepted practice to load dynamic controls in OnInit, so that they get the full control lifecycle. I'm not sure I particularly understand your situation though - if you're loading a control based on a button click, why would it have viewstate at that point? On the next OnInit, you should load the control again (I usually use a page level Viewstate item to track that a particular control needs to be loaded) so that it can restore from Viewstate. Something like:
在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;
}
}
The slightly more interesting bit, though, is that according to catch-up events - it really shouldn't matter. The callstack for dynamically loading a control looks something like:
然而,稍微有趣一点的是,根据追赶事件 - 它确实无关紧要。用于动态加载控件的callstack类似于:
Control.Controls.Add(Control)
Control.AddedControl(Control)
Control.LoadViewStateRecursive(object)
Control.LoadViewState(object)
Taking Label
as an example, it overrides LoadViewState
and pulls it's Text
property directly from ViewState. TextBox is similar. So, by my reading, it should be OK to add at any point, and then access ViewState. That doesn't seem to be jive with my experience, though, so further investigation seems warranted.
以Label为例,它会覆盖LoadViewState并直接从ViewState中提取它的Text属性。 TextBox类似。因此,通过我的阅读,可以随时添加,然后访问ViewState。但是,根据我的经验,这似乎并不合适,因此需要进一步调查。
#2
4
I don't think I can add anything that this article doesn't cover.
我不认为我可以添加本文未涵盖的任何内容。
Look specifically at the Life Cycle Events section.
请特别注意生命周期事件部分。
#3
1
I'm surprised but interested about your results. When I work with dynamic controls I always add them in Page_Init
. Anything else doesn't work. But you are right - how do you do it if you are adding them in response to a button click.
我很惊讶但对你的结果很感兴趣。当我使用动态控件时,我总是在Page_Init中添加它们。其他任何东西都不起作用。但你是对的 - 如果你是为了响应按钮点击而添加它们,你会怎么做?
The only way I have found is by examining Request.Form("__EVENTTARGET")
collection at PageInit
. This contains the control ID of the control that has triggered the postback so for instance a button click. It will of course be qualified by the naming containers it appears in. Once you have identified the 'event' by this method you can add the controls you want.
我找到的唯一方法是在PageInit上检查Request.Form(“__ EVENTTARGET”)集合。这包含触发回发的控件的控件ID,例如按钮单击。它当然会被它出现的命名容器限定。一旦你通过这种方法识别出'event',就可以添加你想要的控件。
It is of course all a bit hacky but it's the only way I found of doing these things. It does work.
它当然有点hacky但它是我发现做这些事情的唯一方法。它确实有效。
It's interesting that the ViewState
is available on PreRender
if you add the controls at Page_Load
. But as the above link indicates it too late to help you then. The controls state is rehydrated during the load cycle. If it's not there then your control state or dynamic controls are just going to disappear.
有趣的是,如果在Page_Load中添加控件,ViewState可在PreRender上使用。但是,由于上面的链接表明它来不及帮助你。控制状态在加载循环期间被再水合。如果不存在那么你的控制状态或动态控制就会消失。
#4
0
Did you try to use LoadComplete
event?
您是否尝试使用LoadComplete事件?
Use this event for tasks that require that all other controls on the page be loaded.
将此事件用于需要加载页面上所有其他控件的任务。
This is fired after PageLoad
and all events (ButtonClick, etc.), so your UserControls are are loaded in ButtonClick events, and in LoadComplete
their ViewState is already initialized.
这是在PageLoad和所有事件(ButtonClick等)之后触发的,因此您的UserControls在ButtonClick事件中加载,而在LoadComplete中,它们的ViewState已经初始化。