Viewstate and controls in ASP.NET

…衆ロ難τιáo~ 提交于 2019-12-12 07:35:29

问题


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:

  1. If usercontrolA is loaded from OnInit of a Page, then his viewstate will be available in OnLoad. All other controls that usercontrolA loads from it's OnInit, will have their viewstate ready in their OnLoad.
  2. If usercontrolA is loaded from OnLoad of a Page, then his viewstate will be available in OnPreRender. All other controls that usercontrolA loads from it's OnLoad, will have their viewstate available in their OnPreRender.
  3. If usercontrolA is loaded from an event (Example: button click. Events fire after OnLoad and before OnPreRender) 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.


回答1:


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:

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:

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.




回答2:


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




回答3:


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 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.

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 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.




回答4:


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 in LoadComplete their ViewState is already initialized.



来源:https://stackoverflow.com/questions/9099397/viewstate-and-controls-in-asp-net

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!