Viewstate loosing ASP.Net Grids?
I ran into a strange problem today that i wanted to share with you.
I had a page with a DataGrid on it, and for some reason, when i posted back to the page, the grid showed zero items in the collection. I had no code messing with the viewstate of the pages or controls, so i was really stumped.
The page this datagrid was on had a lot of complexity, so i tried to simplify the page to find the problem out. I managed to create one test page that reproduced the problem.
This was the markup:
...
<body>
<form id="form1" runat="server">
<div>
<asp:DataGrid ID="dgTeste" runat="server" DataMember="TestTable">
</asp:DataGrid>
<asp:GridView ID="gvTeste" runat="server" DataMember="TestTable">
</asp:GridView>
<cc2:UpdatedPanelControl ID="UpdatedPanelControl1" runat="server">
</cc2:UpdatedPanelControl>
<asp:Button ID="btnPostBack" runat="server" Text="PostBack" />
</div>
</form>
</body>
...
And the codebehind was like so :
...
public partial class _Default : System.Web.UI.Page
{
protected DataSet test = new DataSet();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
test = new DataSet();
test.Tables.Add("TestTable");
test.Tables["TestTable"].Columns.AddRange(new DataColumn[] { new DataColumn("Column1"), new DataColumn("Column2") });
test.Tables["TestTable"].Rows.Add(new object[] { "1", "1" });
test.Tables["TestTable"].Rows.Add(new object[] { "2", "2" });
gvTeste.DataSource = test;
gvTeste.DataBind();
dgTeste.DataSource = test;
dgTeste.DataBind();
}
Response.Write("GridView Rows : " + gvTeste.Rows.Count + "<br>");
Response.Write("GridView Rows : " + dgTeste.Items.Count);
}
}
...
Now, you'll note i've got a user control on the page that is not shown. Well, the code for that control is this :
...
public class UpdatedPanelControl : Panel
{
protected override void OnInit(EventArgs e)
{
bool result = TraverseControlCollection(this.Parent);
base.OnInit(e);
}
private bool TraverseControlCollection(Control control)
{
foreach (Control childControl in control.Controls)
{
TraverseControlCollection(childControl);
}
return true;
}
}
...
If you try this combination out, you'll note that the DataGrids do not have any rows on the Postback event after you click the button.
The reason for this is the TraverseControlCollection(this.Parent); line. If you remove this line from the user control, all will work as expected. Apparently you cannot traverse the control tree while on an OnInit event. This excellent post might shed some light on why this happens, but i really didn't find any information on it.
Hope that this will give you at least one hint on why you might be loosing Viewstate in your ASP.Net controls.