gridview 中按钮的唯一 ID?

Unique ID's for buttons in gridview?

508 扫描标记了一个事实,即我们在网格视图中的按钮具有相同的 ID,我想知道如何解决这个问题。对于其中一些按钮,我们可以完全删除 ID,它们似乎不会影响功能,但实际上其他按钮确实有 enables/disables 它们基于其他因素的后端代码。这是前端代码:

<asp:TemplateField HeaderText="Accept" ItemStyle-HorizontalAlign="Center">
                                    <ItemTemplate>
                                        <asp:Button
                                            ID="btnAccept"
                                            runat="server"
                                            Text="Accept Data"
                                            CssClass="inherited"
                                            CommandName="AcceptData"
                                            CommandArgument="<%# ((GridViewRow) Container).RowIndex %>" />
                                    </ItemTemplate>
                                    <ItemStyle HorizontalAlign="Center"></ItemStyle>
                                </asp:TemplateField>

下面是与此按钮相关的一些后端代码:

protected void gvDashboard_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        try
        {
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                int rowIndex = e.Row.RowIndex;

                Button btnAccept = e.Row.FindControl(@"btnAccept") as Button;
                Button btnRemove = e.Row.FindControl(@"btnRemove") as Button;

                bool errors = (bool)gvDashboard.DataKeys[e.Row.RowIndex][@"Errors"];
                string fileType = (string)gvDashboard.DataKeys[e.Row.RowIndex][@"FileType"];
                string processingStatus = (string)gvDashboard.DataKeys[e.Row.RowIndex][@"ProcessingStatus"];
                bool accepted = (bool)gvDashboard.DataKeys[e.Row.RowIndex][@"Accepted"];

                int records = 0;
                if (gvDashboard.DataKeys[e.Row.RowIndex][@"Records"] is System.DBNull)
                {
                    int recordsColumnIndex = Utilities.GetColumnIndexByHeaderText(gvDashboard, @"Records");
                    e.Row.Cells[recordsColumnIndex].Text = @"0";
                }
                else
                {
                    records = (int)gvDashboard.DataKeys[e.Row.RowIndex][@"Records"];
                }

                
                if (fileType == @"CN" || fileType == @"CP")
                {
                    if ((DBNull.Value.Equals(gvDashboard.DataKeys[e.Row.RowIndex][@"ZipId"]))
                        || ((int)gvDashboard.DataKeys[e.Row.RowIndex][@"ZipId"] == 0))
                    {
                        // CN or CP did not come from a zip file
                        if ((accepted))
                        {                                
                            btnAccept.Enabled = false;                                
                            btnRemove.Enabled = false;
                        }
                    }
                    else
                    {
                        btnAccept.Enabled = false;
                        btnRemove.Enabled = false;
                    }
                }
                
                if (accepted || processingStatus == @"I" || processingStatus == @"N")
                {
                    btnAccept.Enabled = false;
                }
            }
        }
        catch (Exception ex)
        {
            DAL.ErrorLog(@"FilteredDashboard.gvDashboard_RowDataBound: Row: " + e.Row.RowIndex.ToString() + "  " + ex.Message);
        }
    }

理想情况下,我希望能够在前端 ID 上添加一个自动生成的数字,但随后使用相同的初始字符串(如 'btnAccept' 或 'btnRemove')考虑 ID他们的附加数字后缀。这可能吗?

ASP.NET Webforms 自动为每个控件生成按钮 ID,除非您将其设置为

 ClientIDMode="Static"

如果您想确保 ID 是唯一的,请设置

 ClientIDMode="AutoID" //this is the default setting for all webform controls, and autogenerates an ID

所以问题可能来自其他地方,您可以在浏览器的检查器中自行检查。

如 Zee 在回答中所述 - 您可以使用每行一个名称的查找控件 - 但是,每一行控件 - 包括按钮都有自己的 ID。

这个问题不应该存在——一般来说从来都不是问题。 GV 的每一行都会为每一行控件自动生成新的 ID。但是,在生成新的“id”时,您可以在行数据绑定事件上使用带有控件名称的查找控件而不会出现问题。

此外,您真的不需要 save/put 在 hte 按钮命令参数的行索引中。事实上,您还可以获得数据库主键 - 甚至不显示或在每一行中显示主键。

假设您设置了数据键(比如 PK“id”列),那么您可以对 gv 行上的按钮使用简单的按钮行单击事件。

您不能双击按钮来添加事件(因为它在 GV 中),但您可以像这样使用 intel-sense:

只需输入 onclick= ,当你点击“=”时,你会得到这样的情报:

因此,您可以选择创建新活动。

现在,在这个飞机珍按钮事件中你可以

Get any value or control of that row.
Get the row index - no need to put in markup
Get the row primary key database row ID - again no need to have in markup.

所以,按钮后面的代码可以如下所示:

    protected void Button1_Click(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        GridViewRow gRow = btn.NamingContainer as GridViewRow;

        Debug.Print("Row index click = " + gRow.RowIndex);
        Debug.Print("Data base PK ID = " + GridView1.DataKeys[gRow.RowIndex]["ID"]);
        // And you are free to using gRow.FindControl, or even the cells collection
        // for non templated values.
        // eg: gRow.Cells[0].Text

输出:

Row index click = 3
Data base PK ID = 11

注意我是如何使用数据键设置的。这对于安全性来说非常好,因为我不必向客户端公开所使用的数据库行 PK id。并注意我是如何获取当前的 GV 行索引的——同样,所有这些都不必在实际的 gv 行中放置或弄乱那些东西。所以,你甚至不需要使用命令参数。而且您也不需要使用 commandName 。如果您希望 Gv selected index 事件触发,您只需要设置 CommandName。 (所以,你可能需要它),但作为一般规则,只需放入一个平面简按钮 - 连接事件,并像我一样使用“命名容器”获取当前行。然后你得到 GV 行,有了它你就拥有了你需要的一切——包括行索引,甚至如我指出的那样使用数据键。

事实上,这意味着在大多数情况下我不会为内置的 GV 事件烦恼 - 在大多数情况下它们不值得你花时间。