<p>I have a rather complex page that dynamically builds user controls inside of a repeater. This repeater must be bound during the Init page event before <code>ViewState</code> is initialized or the dynamically created user controls will not retain their state.</p>

<p>This creates an interesting Catch-22 because the object I bind the repeater to needs to be created on initial page load, and then persisted in memory until the user opts to leave or save.</p>

<p>Because I cannot use <code>ViewState</code> to store this object, yet have it available during Init, I have been forced to store it in Session.</p>

<p>This also has issues, because I have to explicitly null the session value during non postbacks in order to emulate how <code>ViewState</code> works.</p>

<p>There has to be a better way to state management in this scenario. Any ideas?</p>

<p><strong>Edit:</strong> Some good suggestions about using <code>LoadViewState</code>, but I'm still having issues with state not being restored when I do that.</p>

<p>Here is somewhat if the page structure</p>

<p>Page --> UserControl --> Repeater --> N amount of UserControls Dynamicly Created.</p>

<p>I put the overridden <code>LoadViewState</code> in the parent <code>UserControl</code>, as it is designed to be completely encapsulated and independent of the page it is on. I am wondering if that is where the problem is.</p>

[{'answer_id': 45181, 'author': 'Greg Hurlman', 'author_id': 35, 'author_profile': 'https://Stackoverflow.com/users/35', 'pm_score': 1, 'selected': False, 'text': '<blockquote>\n  <p>This also has issues, because I have to explicitly null the session value during non postbacks in order to emulate how ViewState works.</p>\n</blockquote>\n\n<p>Why do you <strong>have</strong> to explicitly null out the value (aside from memory management, etc)?  Is it not an option to check Page.IsPostback, and either do something with the Session variable or not?</p>\n'}, {'answer_id': 45368, 'author': 'DancesWithBamboo', 'author_id': 1334, 'author_profile': 'https://Stackoverflow.com/users/1334', 'pm_score': 1, 'selected': False, 'text': '<p>I have always recreated my dynamic controls in the LoadViewState event.  You can store the number of controls needed to be created in the viewstate and then dynamically create that many of them using the LoadControl method inside the LoadViewState event.  In this event you have access to the ViewState but it has not been restored to the controls on the page yet.</p>\n'}, {'answer_id': 45928, 'author': 'Ben Scheirman', 'author_id': 3381, 'author_profile': 'https://Stackoverflow.com/users/3381', 'pm_score': 0, 'selected': False, 'text': "<p>1)  there's probably a way to get it to work...  you just have to make sure to add your controls to the tree at the right moment.  Too soon and you don't get ViewState.  Too late and you don't get ViewState.</p>\n\n<p>2)  If you can't figure it out, maybe you can turn off viewstate for the hole page and then rely only on querystring for state changes?  Any link that was previously a postback would be a link to another URL (or a postback-redirect).</p>\n\n<p>This can really reduce the weight of the page and make it easier to avoid issues with ViewState.</p>\n"}, {'answer_id': 46306, 'author': 'Daniel Auger', 'author_id': 1644, 'author_profile': 'https://Stackoverflow.com/users/1644', 'pm_score': 0, 'selected': False, 'text': "<pre><code>protected override void LoadViewState(object savedState)\n{\n   // Put your code here before base is called\n   base.LoadViewState(savedState);\n}\n</code></pre>\n\n<p>Is that what you meant? Or did you mean in what order are the controls processed? I think the answer to that is it quasi-random.  </p>\n\n<p>Also, why can't you load the objects you bind to before Page_Load? It's ok to call your business layer at any time during the page lifecycle if you have to, with the exception of pre-render and anything after.</p>\n"}, {'answer_id': 47861, 'author': 'Daniel Auger', 'author_id': 1644, 'author_profile': 'https://Stackoverflow.com/users/1644', 'pm_score': 0, 'selected': False, 'text': '<blockquote>\n  <p>I have to explicitly null the session\n  value during non postbacks in order to\n  emulate how ViewState works.</p>\n</blockquote>\n\n<p>I\'m still foggy as to why you can\'t store whatever object(s) you are binding against in session. If you could store that object in session the following should work:</p>\n\n<ol>\n<li>On first load bind your top user control to the object during OnPreInit. Store the object in session. Viewstate will automatically be stored for those controls. If you have to bind the control the first time on Page_Load that is ok, but you\'ll end up having two events that call bind if you follow the next step.</li>\n<li>On postback, rebind your top user user control in the OnPreInit method against the object you stored in session. All of your controls should be recreated before the viewstate load. Then when viewstate is restored, the values will be set to whatever is in viewstate. The only caveat here is that when you bind again on the postback, you have to make 100% sure that the same number of controls are created again. The key to using Repeaters, Gridviews etc... with dynamic controls inside of them is that they <strong>have</strong> to be rebound on every postback before the viewstate is loaded. OnPreInit is typically the best place to do this. There is no technical constraint in the framework that dictates that you must do all your work in Page_Load on the first load.</li>\n</ol>\n\n<p>This should work. However, if you can\'t use session for some reason, then you\'ll have to take a slightly different approach such as storing whatever you are binding against in the database after you bind your control, then pulling it out of the database and rebinding again on every postback.  </p>\n\n<p>Am I missing some obvious detail about your situation? I know it can be very tricky to explain the subtleties of the situation without posting code. </p>\n\n<p>EDIT: I changed all references to OnInit to OnPreInit in this solution. I forgot that MS introduced this new event in ASP.NET 2.0. According to their <a href="http://msdn.microsoft.com/en-us/library/ms178472.aspx" rel="nofollow noreferrer">page lifecycle documentation</a>, OnPreInit is where dynamic controls should be created/recreated.</p>\n'}, {'answer_id': 48000, 'author': 'mattruma', 'author_id': 1768, 'author_profile': 'https://Stackoverflow.com/users/1768', 'pm_score': 0, 'selected': False, 'text': '<p>When creating dynamic controls ... I only populate them on the initial load.  Afterwords I recreate the controls on postback in the page load event, and the viewstate seems to handle the repopulating of the values with no problems. </p>\n'}, {'answer_id': 276435, 'author': 'William Gross', 'author_id': 35349, 'author_profile': 'https://Stackoverflow.com/users/35349', 'pm_score': 2, 'selected': False, 'text': "<p>The LoadViewState method on the page is definitely the answer. Here's the general idea:</p>\n\n<pre><code>protected override void LoadViewState( object savedState ) {\n  var savedStateArray = (object[])savedState;\n\n  // Get repeaterData from view state before the normal view state restoration occurs.\n  repeaterData = savedStateArray[ 0 ];\n\n  // Bind your repeater control to repeaterData here.\n\n  // Instruct ASP.NET to perform the normal restoration of view state.\n  // This will restore state to your dynamically created controls.\n  base.LoadViewState( savedStateArray[ 1 ] );\n}\n</code></pre>\n\n<p>SaveViewState needs to create the savedState array that we are using above:</p>\n\n<pre><code>protected override object SaveViewState() {\n  var stateToSave = new List&lt;object&gt; { repeaterData, base.SaveViewState() };\n  return stateToSave.ToArray();\n}\n</code></pre>\n\n<p>Don't forget to also bind the repeater in Init or Load using code like this:</p>\n\n<pre><code>if( !IsPostBack ) {\n  // Bind your repeater here.\n}\n</code></pre>\n"}]
['https://Stackoverflow.com/questions/45176', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/1965/']