【问题标题】:GridView OnRowCommand not fired the first timeGridView OnRowCommand 第一次未触发
【发布时间】:2012-07-10 19:11:59
【问题描述】:

这可能看起来像重复,但我不这么认为。我已经搜索过stackoverflow,可能还不够。

这是我的挑战:

<asp:LinkButton runat="server" ID="DeleteRow" CommandName="deleterow" 
   CommandArgument='<%# Eval("ID") %>' Text="Delete" 
   OnClientClick="return confirm('Are you sure you want to delete this record?');" /> 

如果您第一次单击该链接,则不会触发 OnRowCommand。当你第二次点击它时,它就起作用了。

我查看了源代码并发现了这些差异。

//When you first load the page: the GUID is the PK for that row 
1. javascript:__doPostBack('ctl00$content$gvSchoolClasses$58fd1759-f358-442e-bf73-2e9cedfc27e8$DeleteRow','')

//After the link was clicked the first time, the link changed and the ID empty, but works
2. javascript:__doPostBack('ctl00$content$gvSchoolClasses$ctl02$DeleteRow','')

我从asp:LinkButtonhref 复制了两个代码,用于点击前和点击后。

怎么了?我的页面上只有一个其他事件RowDataBound

  protected void gvSchoolClasses_RowDataBound(object sender, GridViewRowEventArgs e)
  {
        e.Row.ID = Guid.NewGuid().ToString();
  }

  protected void Page_Load(object sender, EventArgs e)
  {
        CheckAuthentication();

        if (!Page.IsPostBack)
        {
            ClassesAcademicYearLabel.Text = "- Year " + Setting.Year;
            //FillClassesList();  //filling some combo boxes. Have checked the codes here too
            //FillLettersList();  //they didn't affect the Grid
            FillGrid();
        }

        ClassErrorLabel.Visible = false;

  }

【问题讨论】:

  • 介意分享您的RowDataBound 事件处理代码吗?我很好奇您为什么将其排除为问题来源
  • 我相信里面的代码应该不会影响到linkBut​​ton。影响网格
  • gvSchoolClasses.DataBind() 在哪里被调用? Page_Load?

标签: c# asp.net gridview


【解决方案1】:

通过在RowDataBound 事件中设置行的 ID 属性,您已经创建了正在观察的问题。

由于RowDataBound 事件在页面控件已添加到集合之后才会触发,因此 ASP.NET 无法更新已计算的客户端引用。因此,该命令不会以您期望的方式被触发。

我注意到您已经将 CommandArgument 属性设置为在 RowDataBound 事件中生成的 ID,这也可能是您的问题的一部分(取决于事件触发的顺序;我没有方便的管道图)。

编辑:对此的快速解决方法可能是简单地将 ClientID 属性(抱歉,不是确切的名称,但智能感知应该让您了解它的其余部分)为某种手动,而不是自动确定。这样,您设置的 ID 就不会被框架更改。

要详细说明您看到此问题的原因,请考虑显示的客户端 ID:

ctl00$content$gvSchoolClasses$ctl02$DeleteRow

通过获取声明的 ID (DeleteRow) 并连续向上遍历控件层次结构并将父 ID 附加到字符串,可以保证此 ID 是唯一的(对于此页面)。 JS 代码可以确信将这个字符串传递给 getElementById 将以一致、可预测的方式运行。

为了能够生成所述 ID,层次结构中的所有控件必须已经存在并由渲染引擎解释。

现在让我们考虑一下当控件的 ID 属性发生更改时会发生什么(注意这不是 ClientID,而只是名称为 ID 的属性)。

ctl00$content$gvSchoolClasses$58fd1759-f358-442e-bf73-2e9cedfc27e8$DeleteRow

您会注意到,它现在具有您生成并分配给它的 GUID,而不是行的命名容器 (cl02)。尝试使用先前分配的 ID 访问此容器的客户端 JS 将感到失望,因为它将不再按预期工作!

当 ASP.NET 控件通过调用 javascript:__doPostBack('ctl00$content$gvSchoolClasses$58fd1759-f358-442e-bf73-2e9cedfc27e8$DeleteRow','') 触发回发时

回发会发生得很好而且很花哨,但是(您可以通过检查回发的表单参数来验证这一点)当服务器处理请求时,它将尝试(从视图状态)重新水合一个不不存在。因此,它将创建一个不知道已发出命令的控件的新实例(具有正确的 ID),因此永远不会触发 XXXCommand 事件。由于没有发生数据绑定(它是回发,并且您的代码正确检查该条件),ID 永远不会重置,并且可以正常触发命令

【讨论】:

  • 从 RowDataBound 中删除 e.Row.ID 有效。我认为解释是引入的Guid.NewGuid 与回发方法中的预期字符串混淆了。谢谢。
  • 感谢您的解释。我想问这个,但我觉得我会谷歌它。
  • 精彩完美的解释
【解决方案2】:

不要更改 RowDataBound 事件中的 Row.ID。在网格中更改不同的值,或者只是在您的 gridview 标记中执行此操作:

CommandArgument=''

如果您想在后面的代码中执行此操作,可以执行以下操作:

protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            LinkButton deleteRow = (LinkButton)e.Row.FindControl("DeleteRow");
            if (deleteRow != null)
                deleteRow.CommandArgument = Guid.NewGuid().ToString();
        }

【讨论】:

  • 这是一段我没有使用的行编辑代码,我改成了你刚才建议的&lt;%: Guid.NewGuid.ToString(); %&gt;。所以它现在是多余的,造成了麻烦。谢谢。
【解决方案3】:

您需要将行索引设置为链接按钮的 CommandArgument 而不是 guid

正如你所说,它在第二次工作,但 html 如下所示

//After the link was clicked the first time, the link changed and the ID empty, but works
2. javascript:__doPostBack('ctl00$content$gvSchoolClasses$ctl02$DeleteRow','')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-21
    • 1970-01-01
    相关资源
    最近更新 更多