While working on AJAX support for r.a.d.calendar, one of our relatively new controls, I came across a very interesting issue with the ASP.NET TextBox control. The problem was related to ViewState management, or better said, the absence of such. The TextBox simply didn’t seem to handle any ViewState information and the TextBox values were not persisted and reloaded correctly after PostBack.
What I was doing wasn’t rocket science - I wanted to make the TextBox (System.Web.UI.WebControls.TextBox) persist its value when the user scrolls forward or backward through the month views. My first thought was that I’m brain-dead and have had too much cups of coffee. The second thing that came to my mind was that there may be a problem with the ViewState management. Everything was just fine and worked correctly, and only few types of controls were showing that type of behavior so I quickly had to dismiss this possibility as well.
It was hard to swallow this random behavior and I started poking around to find the roots of that evil. I debugged the code and saw a private property SaveTextViewState, which is not documented anywhere, but looked suspicious. What made things even more interesting was that the values of the TextBoxes inside the calendar were false.
After googling I found that this is the property that controls the saving of the content e.g. the text in the ViewState. When the property is set to “false” no content is persisted in the ViewState:
SaveTextViewState property is used to prevent saving the Text property value into ViewState when TextBox is in password mode, or when its TextChanged event has no listeners (that is, no event handlers wired) while TextBox is in use (enabled, visible).
Using Lutz Roeder’s Reflector I managed to find a little bit more information than is mentioned in the documentation:
private bool SaveTextViewState
{
get
{
if (this.TextMode == TextBoxMode.Password)
{
return false;
}
if (((base.Events[TextBox.EventTextChanged] == null) && base.IsEnabled) && (this.Visible && (base.GetType() == typeof(TextBox))))
{
return false;
}
return true;
}
}
In a nutshell - the textbox counts on restoring/updating its text value from the post data upon postback. The Text property is preserved in the viewstate only when the control is hidden.
So to have content persistence through ViewState, you have a few options:
1. the event TextChanged of TextBox must be wired
2. the TextBox class must be disabled, hidden, or be a custom class inherited from TextBox.
Something else that matters - the TextBox must NOT be a password input - if it is, it will not persist the content either.
It would be interesting to know whether anyone reading this post has battled with the same problem…