Search code examples
.netdynamicuser-controlspostback

Dynamically created form values persisting after postback


I have a usercontrol which contains dynamically generated webcontrols (TextBox, DropDownList, etc...)

The usercontrol is loaded on certain button click events.

On the usercontrol, there are occasionally postback events which need to be processed (Button.OnClick, etc...).

In order to accommodate the fact that the usercontrol is loaded on a click event, during Page_Load() of the usercontrol's parents, I'm re-executing the code that loads the usercontrol.

IE - I have, essentially, the following:

public partial class parentPage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        If(Page.IsPostBack)
        {
            // Conditions are usually here to make sure this only happens when I want it to
            userControl.LoadUserControl();
        }
    } 

    protected void Button_Click(object sender, EventArgs e)
    {
        userControl.LoadUserControl();
    }
}

public partial class userControl : System.Web.UI.UserControl
{
    public void LoadUserControl()
    {
        // Generate dynamic controls and bind events
    }

    protected void Button_Click(object sender, EventArgs e)
    {
        // Do stuff
    }
}

The problem I'm facing is that, after the Button_Click() event of the usercontrol is processed, the next time I click the button on the parent, the usercontrol's dynamically generated fields are somehow being automatically populated by what they were before the usercontrol's button was clicked - despite the fact that I'm explicitly setting the values when the LoadUserControl() function is called during the parent's button click.

What's even stranger is that the fields which are populated aren't necessarily consistent. In some cases TextBoxes have the correct text but DropDownLists have the old selected item. In other cases, DropDownLists are properly selected, but the TextBoxes retain the old text.

Does anyone have any suggestions or insights? I've tried a million different ideas and nothing seems to work.

** EDIT **

A bit of insight, perhaps - if I set the usercontrol to ViewStateMode=Disabled, it seems to solve the problem. I am reluctant to do this though, as I'm really not sure whether it will affect other functionality. I've already discovered a few glitches with the change, and I've a feeling even if I fix those, I'll end up finding more later. So hopefully any solution will not require such a drastic change. Perhaps the fact that it does solve this problem may help find a more elegant solution, though?

** EDIT 2 **

Debugging using dotPeek into the framework for System.Web.UI.ControlCollection.Add() reveals that, after adding the control to the collection, System.Web.UI.Control.AddedControl() is called. At the end of that, System.Web.UI.Control.LoadViewStateRecursive() is called. It's within there that the trouble arises. Despite the fact that this is a dynamically generated control, it still seems to persist in the ViewState. Continuing to dig...


Solution

  • Alright! After two days of debugging through the deep, dark innards of the .NET Framework, I've finally arrived at a solution.

    I'm still not really sure why this problem is happening, but the solution was to disable the ViewState for the controls which I want to manually load, but only on initial load.

    Since the loading of the controls is happening on Postback, I couldn't go with a simple if(!Page.IsPostBack) option, so what I did use a function which I'd already written, that returns the Postback Control ID of the control doing the Postback. If the ID matches with the buttons that I know are being used to initially load the controls, then when creating the different inputs, I set their ViewStateMode to Disabled, and, for bonus points, also set the EnableViewState to false.

    The key is that, when those controls then do their own Postbacks (IE, DropDownList.SelectedIndexChanged, Button.Click, etc...), the ViewStateMode for them is enabled - so all works properly!