If I recursively traverse the controls of a page, the RowCommand event is no longer fired by LinkButtons in a GridView. In fact, it looks like the ViewState for the GridView is lost. Why? How can I work around this?
The code below will work fine until you uncomment the //recurse(this.Controls) line. Then, when you hit the link, the GridView disappears and the RowCommand is never fired.
The complete <body> of my page:
<form id="form1" runat="server">
<asp:GridView ID="gv" AutoGenerateColumns="False" runat="server" onrowcommand="gv_RowCommand">
<Columns><asp:TemplateField HeaderText="Link"><ItemTemplate>
<asp:LinkButton ID="lnk" runat="server" CommandArgument = 'xxx'>xxx</asp:LinkButton>
</ItemTemplate></asp:TemplateField></Columns>
</asp:GridView>
</form>
My code behind:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
//recurse(this.Controls);
}
private static void recurse(ControlCollection controls)
{
foreach (Control control in controls)
recurse(control.Controls);
}
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
var dt = new DataTable();
dt.Columns.Add("Link", typeof(string));
DataRow dr = dt.NewRow();
dr["Link"] = "google.com";
dt.Rows.Add(dt);
DataSet ds = new DataSet();
ds.Tables.Add(dt);
gv.DataSource = ds;
gv.DataBind();
}
}
protected void gv_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (this.Application["counter"] == null)
this.Application["counter"] = 0;
this.Application["counter"] = (int)this.Application["counter"] + 1;
Response.Write("JUNK" + this.Application["counter"]);
}
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
@jbl found something that explained this well enough for me (thanks for the search skills!). This problem has been seen before here: http://forums.asp.net/t/1043999.aspx/1
Summarizing that page, accessing the .Controls property of a GridView in any way during the Init phase will destroy its ViewState. There is no explanation for why, but it has been observed anyway.
There is a workaround on that page that is good enough for me. If you check for each control to see if it .HasControls() and don’t access its .Controls property if it doesn’t, the ViewState will not be lost, and consequently events will fire normally.
P.S. I’m GUESSING this is a bug, but of course it can’t be changed forevermore because of backwards compatibility 🙁
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0