2012-07-10 21 views
2

这可能看起来像重复,但我不这么认为。我已经搜索了stackoverflow,可能还不够。GridView的OnRowCommand第一次没有开通

这里是我的挑战:

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

    } 
+0

介意分享你的'RowDataBound'事件处理代码?我很好奇你为什么排除它作为问题来源 – 2012-07-10 19:27:05

+0

我相信里面的代码不应该影响linkBut​​ton。那影响了网格 – codingbiz 2012-07-10 19:30:20

+0

哪里调用了'gvSchoolClasses.DataBind()'? 'Page_Load'? – 2012-07-10 19:32:58

回答

3

通过设置行的ID属性在RowDataBound情况下,你已经创建你观察问题。

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

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

编辑:这可以简单地设置ClientID属性(对不起,不是确切的名称,但intellisense应该让你的方式的其余部分)到某种手动,而不是自动确定。这样,您设置的ID永远不会被框架更改。

更详细地说明为什么你会看到这个问题了一下,考虑客户端ID的呈现:

ctl00$content$gvSchoolClasses$ctl02$DeleteRow

此ID通过采取保证是(本页)独特声明ID(DeleteRow),并连续向上走控制层次结构并将父ID预先添加到字符串中。 JS代码可以确信,将该字符串传递给getElementById的行为将以一致的,可预测的方式进行。

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

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

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

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

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

回传将会发生很好,很正常,但(你可以通过检查回发的形式PARAMS验证这一点)当服务器处理请求时,它将尝试从视图状态中补充一个不存在的控件。因此,它将创建一个新的控件实例(使用正确的ID),它不知道命令已经发出,所以事件(s)永远不会被触发。由于没有发生数据绑定(这是回发,并且您的代码正确检查该情况),因此ID永远不会重置,并且该命令可以正常触发

+0

从RowDataBound工作中删除e.Row.ID。我认为解释是引入的'Guid.NewGuid'与postback方法中预期的字符串混淆了。谢谢。 – codingbiz 2012-07-10 20:03:43

+0

感谢您的解释。我想要这个,但我觉得我会谷歌它。 – codingbiz 2012-07-10 20:11:59

+0

明智和完美的解释 – codingbiz 2012-07-10 22:04:55

0

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

正如你说的第二次合作,但如下图所示

//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','') 
1

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

CommandArgument ='<%:Guid.NewGuid.ToString(); %>”

如果你想做到这一点在后面的代码,你可以做这样的事情:

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

这是一段代码行编辑我留下未使用,我改变了你刚才的建议'<%:Guid.NewGuid.ToString(); %>'。所以现在是多余的现在造成了麻烦。谢谢。 – codingbiz 2012-07-10 20:09:32