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.
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.
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?
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.
Any suggestions and/or links are appreciated.
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:
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:
Taking
Label
as an example, it overridesLoadViewState
and pulls it'sText
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.I don't think I can add anything that this article doesn't cover.
Look specifically at the Life Cycle Events section.
http://msdn.microsoft.com/en-us/library/ie/ms178472.aspx
Did you try to use
LoadComplete
event?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 inLoadComplete
their ViewState is already initialized.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.The only way I have found is by examining
Request.Form("__EVENTTARGET")
collection atPageInit
. 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.It is of course all a bit hacky but it's the only way I found of doing these things. It does work.
It's interesting that the
ViewState
is available onPreRender
if you add the controls atPage_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.