views:

1044

answers:

4

Hello.

I have a problem with ViewState. I have an aspx page that has a treeview on the left and an UpdatePanel with an ASP.NET Panel inside on the right. It is in that inner Panel where I load and unload dynamically user controls. I use that update panel to load dynamically controls.

I also made a custom control for my user controls because I need to pass some values from page. On that constructor I use ViewState to store these values.

The first time I load the user control I call its constructor with parameters. When I reload that user control on each postback I use its normal constructor.

My problem is I the values I've stored on ViewState has become null on successive postback.

Update:

This is a piece of my user control:

public class MyUserControl : System.Web.UI.UserControl
{
private int PKId
{
    get { return ViewState["pkId"] as int; }
    set { ViewState["pkId"] = value; }
}

public MyUserControl(int pkId)
{
    this.PKId = pkId;
}

...
}

I'm following this article to load controls dynamically: http://msdn.microsoft.com/en-us/magazine/cc748662.aspx#id0070065.

Second Update:
I also set the same control ID when I load the user control at first time and on each reaload.

Maybe I can use another method to store these values like input hidden fields or Cache. I've choosen ViewState because I don't want to overload server with Session values for each user.

Third update:

I load the controls with this code:

System.Web.UI.UserControl baseControl = LoadControl(ucUrl) as System.Web.UI.UserControl;
if (baseControl != null)
{
    baseControl.ID = "DestinationUserControl";
    PanelDestination.Controls.Add(baseControl);
}

And reaload with this code:

DynamicControls.CreateDestination ud = this.LoadControl(TrackedUserControl) as DynamicControls.CreateDestination;
if (ud != null)
{
    ud.ID = "DestinationUserControl";
    PanelDestination.Controls.Add(ud);
}

What's happening?

A: 

Adding controls dynamically inside an UpdatePanel is such a bad idea. It generates so much problems.

If it is possible, move the dynamic control creation out of the UpdatePanel and I believe your problem will be solved.

Shay Friedman
I'm so sorry. I make a mistake. It is an UpdatePanel with an ASP.NET Panel inside. It is in that inner Panel where I load and unload dynamically user controls.
VansFannel
+1  A: 

When are you loading the user control? This has to happen in the Init event if you want ViewState to be saved/restored.

Bryan
The user control has some textbox. If they have some text it is restored correctly on postbacks. I'm reloading user control on Page_Load event. I'm following this article to load controls dynamically: http://msdn.microsoft.com/en-us/magazine/cc748662.aspx#id0070065
VansFannel
If that article says to load dynamic controls in Page_Load, it's just flat out wrong. This will work in some cases, but certainly not all, as you've discovered. ViewState restore happens before Page_Load, and that's why your variable is null. No simpler way to explain it.
Bryan
A: 

As Bryan mentioned, you should load your dynamic controls in Page_Init rather than Page_Load.

As this description of the Page Life Cycle explains, by the time the Page_Load event happens, the view state from the postback has already been processed (in PreLoad). If the controls haven't been reloaded yet, the view state has nowhere to go.

PreLoad:

Use this event if you need to perform processing on your page or control before the Load event.

Before the Page instance raises this event, it loads view state for itself and all controls, and then processes any postback data included with the Request instance.

Eric King
Maybe I can use another method to store these values like input hidden fields or Cache. I've choosen ViewState because I don't want to overload server.
VansFannel
Controls can be dynamically added on postback in the Load event, at which time their lifecycle will "catch up" to the current event. See "Catch-up Events for Added Controls" here http://msdn.microsoft.com/en-us/library/ms178472.aspx, and Walkthrough #6 here http://www.codeproject.com/KB/aspnet/aspnetviewstatepagecycle.aspx#Walkthroughs (which excellently illustrates the difference in behavior before and after a control is added to the hierarchy).
gWiz
@gWiz, while walkthrough #6 is interesting, depending on "catch-up" events is problematic at best. Even the walkthrough itself says "it is recommended that you add your dynamic controls during the “PreInit” or “Init” events". That's what I was suggesting to @VansFannel.
Eric King
Don't use PreInit. I've had a bad experience with this... exactly like using Page_Load. And I'm not sure why. Init event is definitely the way to go.
Bryan
+2  A: 

Try storing the control into a local variable once it's loaded/constructed before it's added to the control hierarchy. That allows the ViewState data to be mapped from and to the control. See "Rule 2" here http://chiragrdarji.wordpress.com/2009/05/20/maintain-viewstate-for-dynamic-controls-across-the-postback/.

gWiz
I set the same ID on both cases and it doesn't work.
VansFannel
Ah, ok. My answer is updated. This should do it.
gWiz
Maybe I don't understand your answer but I'm doing in that way like Rule 2. I updated my question with more details.
VansFannel