首页 > 解决方案 > Gridview 删除按钮 - 对象引用错误

问题描述


我正在尝试使用 GridView 在 asp .NET 中开发网页。我希望 GridView 有一个编辑和删除按钮。以下是我对 GridView 的标记:
<asp:GridView ID="EduGrid" CssClass="edugrid table table-striped table-hover table-borderless" runat="server" AutoGenerateColumns="False" GridLines="None" OnRowDeleted="EduGrid_RowDeleted" OnRowDeleting="EduGrid_RowDeleting">
    <Columns>
                 <asp:CommandField SelectText="" ShowSelectButton="True" ControlStyle-CssClass="btn btn-dark btn-sm fa fa-edit" />
                 <asp:CommandField DeleteText="" ShowDeleteButton="true" ControlStyle-CssClass="btn btn-dark btn-sm fa fa-trash" />
                 <asp:BoundField DataField="degree" HeaderText="Degree" SortExpression="degree" />
                 <asp:BoundField DataField="major" HeaderText="Major" SortExpression="major" />
                 <asp:BoundField DataField="year" HeaderText="Passing Year" SortExpression="year" />
                 <asp:BoundField DataField="total marks" HeaderText="Total Marks" SortExpression="total marks" />
                 <asp:BoundField DataField="obt marks" HeaderText="Obtained Marks" SortExpression="obt marks" />
                 <asp:BoundField DataField="division" HeaderText="Division" SortExpression="division" />
                 <asp:BoundField DataField="board" HeaderText="Board/University" SortExpression="board" />
    </Columns>
                                
    <HeaderStyle CssClass="thead-dark" Font-Names="Calibri" Font-Size="Larger" />
    <RowStyle Font-Names="calibri" Font-Size="Medium" />
</asp:GridView>

我在“CandId”页面上还有一个标签,其中包含用于在 GridView 中获取记录并从数据库中删除记录的 ID。但是,由于每个候选人有超过 1 条记录,我想删除基于 2 个参数的记录,即 ID 和度数(第一列)。它仅根据 ID 删除,但会删除该特定 ID 的所有记录,但我只想删除一个特定条目。如果我提供度数列作为参数,它会给出对象引用异常。以下是我在 c# 中的后端代码:

        protected void EduGrid_RowDeleting(object sender, GridViewDeleteEventArgs e)
        {
            GridViewRow row = EduGrid.SelectedRow;
            conn = new SqlConnection(connString);
            string query = "DELETE FROM [Edu Info] WHERE cnic = @cnic AND degree = @degree";
            sqlcmd = new SqlCommand(query, conn);
            sqlcmd.Parameters.AddWithValue("@cnic", lblID.Text);
            sqlcmd.Parameters.AddWithValue("@degree", row.Cells[1].Text);

            try
            {
                conn.Open();
                sqlcmd.ExecuteNonQuery();
                lblInfo.Text = "Record deleted successfully.";
                lblInfo.Visible = true;
                Get_Edu();
            }

            catch (Exception ex)
            {
                lblInfo.Text = "An error occurred. Please contact the administrator.";
                lblInfo.Visible = true;
            }

            finally
            {
                conn.Close();
                conn.Dispose();
                SqlConnection.ClearAllPools();
            }
        }

我认为问题在于 OnRowDeleting 方法不适合与 GridView.SelectedRow 一起使用,并且 .SelectedRow 只能在 OnSelectedIndexChanged 方法中使用。如果是这种情况并且我是对的,我应该怎么做才能解决它?任何人都可以提供解决方案吗?
谢谢。

标签: c#asp.netgridviewwebforms

解决方案


好的,这里有很多问题。而且我不清楚为什么您的数据源不包含数据库的主键。因此,您不需要同时使用 cnic 和 degree 来识别一行。我不记得在我没有 PK ID 的网格中有行。(所以,对你来说很奇怪)。

但是,请记住删除事件不会更改所选索引。事实上,如果你说一个按钮,使用 commandName/CommandText,你会发现行命令首先触发(选定的索引尚未更改),然后触发选定的索引事件。

在您的示例中 - 索引不会改变。

但是,在这种情况下,您可以使用以下命令单击该行:

e.RowIndex

所以,你现在可以这样:

GridViewRow row = EduGrid.Rows[e.RowIndex];

因此,您所拥有的其余部分应该没问题。因此,请记住,对于命令按钮和网格中的大多数按钮,即使(如果要触发)所选索引实际上也会在按钮事件存根之后触发。在某些情况下,理论上您可以将代码移动到选定的索引更改事件 - 但在这种情况下甚至不会触发。所以选定的索引不可用。使用 e.RowIndex 获取该行。

此外,如果您包含数据库中的 PK,则无需使用两列来标识数据库中的该行,而只需使用 PK 行 ID。而且您不必让 PK 甚至显示在网格中。

这就是 DataKeyNames = "PK 行列名" 的用途"

例如:

    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
            DataKeyNames="ID" >

所以,DataKeyNames = "PK FROM 数据库"

因此在上面的 RowDeleting 事件中,然后

e.RowIndex - gets you row index clicked on
e.Keys["ID"]  - gets you database PK

因此,请注意如何(应该)尝试从数据库中设置 DataKeyNames = "primary key"。那么您可以使用 e.Keys["ID"] 获得 PK 行 ID。


推荐阅读