views:

283

answers:

3

I'm writing a custom control in ASP.Net 3.5 WebForms, using ASP.Net AJAX. I'm building a state toggle into the control (expanded and collapsed modes). I've been trying to keep the current state of the control in ViewState, changing it in a server-side event handler manually:

object oExpanded = ViewState[ "Expandedness" ];
if(oExpanded == null)
{
    oExpanded = ListState.Collapsed;
}
ListState lsCurrentState = (ListState) oExpanded;
if(lsCurrentState == ListState.Collapsed)
{
 //code snipped - move to expanded mode here
 ViewState[ "Expandedness" ] = ListState.Expanded;
}
else
{
 //code snipped - move to collapsed mode here
 ViewState[ "Expandedness" ] = ListState.Collapsed;
}

I don't think it should matter, but the actual rendering happens in an updatepanel and the code above is in an event handler that's triggered asynchronously. The problem I have is that on the next postback, ViewState["Expandedness"] returns null. I've tried to use Fritz Onion's Viewstate Decoder tool to look at the actual contents of viewstate between postbacks, but it tells me the serialized data is invalid.

Have I taken a wrong approach here? What's the right way to tackle this problem?

A: 

when do you call this code? if it is called in Page_Init it is too early, and any changes you do to the viewstate will be ignored.

Just a thought

AndreasKnudsen
Good thought, but this code is called inside a subcontrol's event handler (so, lifecycle-wise, it happens after Page_Load and before Page_Prerender). So I should have access to Viewstate.
DDaviesBrackett
A: 

Further investigation: The changes to Viewstate that I make in the sub-control event handler do last as long as Page_Prerender (i.e. later in the event lifecycle of the page), so the problem isn't that Viewstate isn't getting written to. But any subsequent postbacks to the page - synchronous or asynchronous - don't show that value in viewstate.

DDaviesBrackett
+1  A: 

You're right that it's OK for it to be in an UpdatePanel - this shouldn't make any difference.

I suspect that the ViewState is disabled either for your control or for one of its parents: if it's disabled for any parent (all the way up to the page), it'll be disabled for your control.

To get round this, you can use the page's ViewState dictionary instead of the one on your control.

I.e. instead of saying:

this.ViewState[ "Expandedness" ] = ListState.Expanded;

say:

this.Page.ViewState[ "Expandedness" ] = ListState.Expanded;

If it's possible that there's more than one instance of your control on the page, you'll need to ensure the ViewState key is unique, perhaps like this:

this.Page.ViewState[ this.ClientID + "Expandedness" ] = ListState.Expanded;

As an alternative (that will work even if ViewState's disabled for the page), you could consider storing the Expandedness in the ControlState. It's a bit trickier, but google it and you'll find a code sample pretty quickly. It's recommended you store only an absolute minimum of information in the ControlState, but a single flag like this is fine (and actually what it's designed for, really).

teedyay
This was exactly what was causing it! I missed an `EnableViewState="false"` on the page itself. Thanks, teedyay!
DDaviesBrackett