Gridview 删除按钮 - 对象引用错误
Gridview Delete Button - Object Reference Error
我正在尝试使用 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 方法中使用。如果是这种情况并且我是对的,我应该怎么做才能解决它?谁能提供解决方案?
谢谢
好的,这里有很多问题。而且我不清楚为什么您的数据源不包含数据库的主键。因此,您不需要同时使用 cnic 和 degree 来标识一行。我不记得在没有 PK ID 的网格中有行。 (所以,你这边很奇怪)。
但是,请记住删除事件不会更改所选索引。事实上,如果你说一个按钮,使用 commandName/CommandText,你会发现行命令首先触发(选定的索引尚未更改),然后选定的索引事件触发。
在您的示例中 - 索引不会更改。
但是,在那种情况下,您可以通过以下方式点击行:
e.RowIndex
所以,你现在可以这样了:
GridViewRow row = EduGrid.Rows[e.RowIndex];
所以,你所拥有的其余部分应该没问题。因此,请记住,对于命令按钮和网格中的大多数按钮,选定的索引(如果要触发)实际上在按钮事件存根之后触发。在某些情况下,理论上您可以将代码移动到选定的索引更改事件 - 但在这种情况下甚至不会触发。所以选定的索引不可用。使用 e.RowIndex 获取该行。
此外,如果您包含数据库中的主键,则无需使用这两列来标识数据库中的该行,而只需使用主键行 ID。而且您甚至不必在网格中显示 PK。
这就是 DataKeyNames = "PK 行列名称" 的用途
例如:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" >
所以,DataKeyNames = "PK FROM database"
因此在上面的RowDeleting事件中,那么
e.RowIndex - gets you row index clicked on
e.Keys["ID"] - gets you database PK
因此,请注意您可以(应该)如何尝试从数据库中设置 DataKeyNames = "primary key"。然后你可以用 e.Keys["ID"] 得到 PK 行 id。
我正在尝试使用 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 方法中使用。如果是这种情况并且我是对的,我应该怎么做才能解决它?谁能提供解决方案?
谢谢
好的,这里有很多问题。而且我不清楚为什么您的数据源不包含数据库的主键。因此,您不需要同时使用 cnic 和 degree 来标识一行。我不记得在没有 PK ID 的网格中有行。 (所以,你这边很奇怪)。
但是,请记住删除事件不会更改所选索引。事实上,如果你说一个按钮,使用 commandName/CommandText,你会发现行命令首先触发(选定的索引尚未更改),然后选定的索引事件触发。
在您的示例中 - 索引不会更改。
但是,在那种情况下,您可以通过以下方式点击行:
e.RowIndex
所以,你现在可以这样了:
GridViewRow row = EduGrid.Rows[e.RowIndex];
所以,你所拥有的其余部分应该没问题。因此,请记住,对于命令按钮和网格中的大多数按钮,选定的索引(如果要触发)实际上在按钮事件存根之后触发。在某些情况下,理论上您可以将代码移动到选定的索引更改事件 - 但在这种情况下甚至不会触发。所以选定的索引不可用。使用 e.RowIndex 获取该行。
此外,如果您包含数据库中的主键,则无需使用这两列来标识数据库中的该行,而只需使用主键行 ID。而且您甚至不必在网格中显示 PK。
这就是 DataKeyNames = "PK 行列名称" 的用途
例如:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataKeyNames="ID" >
所以,DataKeyNames = "PK FROM database"
因此在上面的RowDeleting事件中,那么
e.RowIndex - gets you row index clicked on
e.Keys["ID"] - gets you database PK
因此,请注意您可以(应该)如何尝试从数据库中设置 DataKeyNames = "primary key"。然后你可以用 e.Keys["ID"] 得到 PK 行 id。