3

如果我递归遍历页面的控件,则 GridView 中的 LinkBut​​tons 不再触发 RowCommand 事件。事实上,看起来 GridView 的 ViewState 丢失了。为什么?我该如何解决这个问题?

在您取消注释该//recurse(this.Controls)行之前,下面的代码将正常工作。然后,当您点击链接时,GridView 消失并且 RowCommand 永远不会被触发。

我的页面的完整<body>

<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>

我背后的代码:

    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"]);
    }
4

1 回答 1

3

@jbl 找到了一些对我来说足够好的解释(感谢搜索技巧!)。这个问题之前在这里看到过:http ://forums.asp.net/t/1043999.aspx/1

总结该页面,.Controls在 Init 阶段以任何方式访问 GridView 的属性都会破坏其 ViewState。没有解释为什么,但无论如何它已经被观察到了。

该页面上有一个对我来说足够好的解决方法。如果您检查每个控件是否有.HasControls(),如果没有则不访问其.Controls属性,ViewState 不会丢失,因此事件将正常触发。

PS我猜这是一个错误,但由于向后兼容性,它当然不能永远更改:(

于 2013-03-14T16:54:26.003 回答