【问题标题】:Dynamically added link button disappeared on button click leaving an empty column动态添加的链接按钮在按钮单击时消失,留下一个空列
【发布时间】:2026-01-30 00:00:01
【问题描述】:

数据网格从几个 xml 文件中读取,因此我动态创建列,并添加了一个模板字段作为最后一列。

使用 RowDataBound 在模板字段中添加一个链接按钮。

Private Sub GridItem_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridItem.RowDataBound
    Try
        If e.Row.RowType = DataControlRowType.DataRow Then
            Dim linkb As New LinkButton
            linkb.Text = "Delete"
            linkb.ID = "LinkDeleteItem"
            linkb.OnClientClick = "javascript:DeleteItem('" & Convert.ToString(e.Row.RowIndex) & "')"
            e.Row.Cells(GridItem.Columns.Count - 1).Controls.Add(linkb)
        End If
    Catch ex As Exception
        lblMessage.Text = ex.Message
    End Try
End Sub

一切正常。

但是,当我单击网格视图外的按钮以打开一个窗口以向网格添加新项目时,链接按钮消失了。但该列仍然存在。

如果我只是关闭新窗口而不保存新数据(这将提示网格重新绑定),则该列保持为空。我必须重新加载 gridview 才能显示链接按钮。

是因为链接按钮是在 rowdatabound 上创建的吗?我该如何解决这个问题?

【问题讨论】:

  • 您是否尝试过仅在第一次加载页面时使用If Not IsPostBackPage_Load 子程序中绑定网格?
  • 当用户选择要打开的 xml 文件时加载网格。所以当页面第一次加载时,网格是空的。
  • 那么当你点击网格视图外的按钮时,是什么导致网格重新绑定呢?
  • 其实我自己也不确定。当我单击按钮时,数据仍然绑定,但缺少链接按钮。
  • 当按钮被点击时它没有到达那个事件,它也没有到达网格填充的子节点。

标签: asp.net gridview dynamic-controls


【解决方案1】:

这是因为 GridView 的 OnRowDataBound 事件在下一次回发时没有被调用。发生这种情况是因为默认情况下 GridView 的 viewstate 设置为 true,即 Gridview 的 EnableViewState 属性为 true。当 ViewState 打开时,Gridview 存储来自相同的数据,并且不会调用 OnRowDataBound 事件。此外,此时视图状态不会应用于您的linkButtons,因为它们不是在page_load 中创建的。

尝试将您的 gridview 的 EnableViewState 属性设置为 false:

<asp:GridView ID="CustomersGridView" 
     OnRowDataBound="CustomersGridView_RowDataBound"
     EnableViewState="false"
  ....  />

或者您也可以将GridView 绑定到page_Load 为:

protected void Page_Load(object sender, EventArgs e)
    {
       CustomersGrIdView.DataBind();
    }

现在,在每次回发后,您的 OnRowDataBound 事件将被调用,因此 LinkButtons 每次都可用。


注意: 将 gridview 的 EnableViewState 属性设置为 false 在一定程度上可能是一种不好的做法,尤其是在数据使用量很大的情况下。每次绑定gridview也是如此。

当使用动态控件时,它们只存在到下一次 postback.ASP.NET 不会重新创建动态添加的控件。如果您下次也需要在回发时重新创建控件,则应在PageLoad 事件处理程序中执行控件创建。

这将使您在动态控件中使用视图状态。即使视图状态通常在Page.Load 事件之前恢复,如果您在PageLoad 事件的处理程序中创建一个控件,ASP.NET 将应用它在PageLoad 事件处理程序结束后拥有的任何视图状态信息。

【讨论】:

  • 你的解释帮助我想到了解决这个问题的方法。在检查gridview中是否有行之后,我在每次回发时重新填充网格,重新绑定它。但我担心这是否会导致将来出现任何错误或错误,或者是否存在大量数据。
  • 是的,您也可以这样做。意识到我的答案中存在但由于我应用了不正确的格式而实际上从答案中丢失了。现已更正。它们可以说是相同的,不会有太大的不同。另外,你的担心是对的。虽然这不会导致任何错误或错误,但唯一的问题是总会有额外的数据库调用。但是,如果性能确实不是问题,那么根据您的要求,这是一个不错的选择。
  • 那么我想这是我将采取的选择。非常感谢您的帮助。
  • 感谢 3 年后的人,这是对我的帮助!我搜索了几个小时,直到找到它并且效果很好
  • 我明白了所有这些,但我不明白为什么不调用动态创建的控件的事件。例如,如果我创建一个带有 OnCheckChanged 事件的复选框并在单击事件上放置一个调试点。它永远不会被触发。我在按钮、DDL 等方面也有同样的问题。page_load 也给我带来了问题,因为我需要数据绑定事件已经触发,因为我需要它知道要呈现哪种类型的控件。 (取决于一列值)