【问题标题】:I can't get the delete link button on gridview to work我无法让gridview上的删除链接按钮工作
【发布时间】:2016-12-14 13:11:55
【问题描述】:

我目前正在使用 Visual Studio 在 C# 中创建一个 asp.net Web 应用程序。我有一个显示来自数据库表的数据的网格视图,并且我已经在我的 .cs 页面中手动添加了数据源,因为我已经将孩子的 DOB 转换为年龄,从而使我能够使用年龄组的下拉列表过滤网格视图。这一切都很好,我遇到的唯一问题是让删除链接按钮工作。如果单击,我需要它从数据库表中完全删除子项。

我首先在设计模式下进入 gridview,添加新列 --> 按钮字段(按钮类型“链接”,命令名称“删除”),然后在我的 .cs 页面中添加以下代码:

protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
    {
        LinkButton lnkRemove = (LinkButton)sender;

        SqlCommand cmd = new SqlCommand();
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "delete from  children where " +
        "childID=@childID";           
        cmd.Parameters.Add("@childID", SqlDbType.VarChar).Value
            = lnkRemove.CommandArgument;
        GridView1.DataSource = source;
        GridView1.DataBind();
    }

当我运行页面并单击任何子项旁边的删除时,我收到以下错误:

我将包含来自我的 .cs 页面的完整代码以及我的源代码。有人可以帮我弄清楚为什么我会收到错误以及为什么删除按钮不会毫无问题地删除吗?提前致谢。

完整的 .CS 代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Configuration;
using System.Data.SqlClient;


namespace Coursework
{
public partial class Testy1 : System.Web.UI.Page
{
    //create a datasource
    SqlDataSource source = new SqlDataSource();

    protected void Page_Load(object sender, EventArgs e)
    {
        //always set some defaults for the sqldatasource
        source.ID = "source1";
        source.ConnectionString = ConfigurationManager.ConnectionStrings["newregDBConnectionString"].ConnectionStr‌​ing;
        source.SelectCommand = "SELECT firstname, dob, DATEDIFF(hour, dob, GETDATE()) / 8766 AS age FROM children ORDER BY age";

        if (!IsPostBack)
        {
            //bind the grid
            GridView1.DataSource = source;
            GridView1.DataBind();
        }
    }       
    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        //the new database query, now with where clause
        source.SelectCommand = "SELECT firstname, dob, DATEDIFF(hour, dob, GETDATE()) / 8766 AS age FROM children WHERE (DATEDIFF(hour, dob, GETDATE()) / 8766 BETWEEN @start AND @end) ORDER BY age";

        //get the end age from the dropdown and cast as int
        int end = Convert.ToInt32(DropDownList1.SelectedValue);

        //get the start int for the filter
        int start = end - 2;

        //if the filter is resetted, make sure the query returns all ages
        if (end == 5)
        {
            start = 5;
            end = 99;
        }

        //replace the parameters in the query
        source.SelectParameters.Add("start", start.ToString());
        source.SelectParameters.Add("end", end.ToString());

        //rebind the grid
        GridView1.DataSource = source;
        GridView1.DataBind();
    }

    protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
    {

    }

    protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
    {
        LinkButton lnkRemove = (LinkButton)sender;

        SqlCommand cmd = new SqlCommand();
        cmd.CommandType = CommandType.Text;
        cmd.CommandText = "delete from  children where " +
        "childID=@childID";           
        cmd.Parameters.Add("@childID", SqlDbType.VarChar).Value
            = lnkRemove.CommandArgument;
        GridView1.DataSource = source;
        GridView1.DataBind();
    }
}

源代码:

 <%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Testy1.aspx.cs" Inherits="Coursework.Testy1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
    <p></p>
    <p></p>
    <p></p>
    <p></p>
    <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="true" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
    <asp:ListItem Text="Filter age" Value="5"></asp:ListItem>  
    <asp:ListItem Text="5 - 7" Value="7"></asp:ListItem>
    <asp:ListItem Text="8 - 10" Value="10"></asp:ListItem>
    <asp:ListItem Text="11 - 13" Value="13"></asp:ListItem>
    <asp:ListItem Text="14 - 16" Value="16"></asp:ListItem>
    </asp:DropDownList>
    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnSelectedIndexChanged="GridView1_SelectedIndexChanged" OnRowDeleting="GridView1_RowDeleting" >
    <Columns>
        <asp:TemplateField HeaderText="Name">
            <ItemTemplate>
                <%# Eval("firstname") %>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="DOB">
            <ItemTemplate>
                <%# Convert.ToDateTime(Eval("dob")).ToString("d MMMM yyyy") %>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:TemplateField HeaderText="Age">
            <ItemTemplate>
                <%# Eval("age") %>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:ButtonField CommandName="Delete" Text="Delete" />
    </Columns>
</asp:GridView>
</asp:Content>

【问题讨论】:

  • 您甚至没有为按钮字段分配CommandArgument
  • 在源代码中还是在.cs页面中?我只在自动连接到没有 .cs 代码的数据源时使用过删除功能,所以我对这种做事方式很陌生!
  • 这里 LinkButton lnkRemove = (LinkButton)sender; 发件人是 GridView 而不是链接按钮
  • 哦,那是我添加到网格视图中的链接按钮的错误代码吗?应该是什么?
  • 我应该补充一点,我的教授告诉我们,我们几乎不需要接触这个项目的源代码,所以在下学期之前我们不会学到太多东西。所以我现在对它不熟悉,也是C#和asp.net的初学者!

标签: c# sql asp.net gridview


【解决方案1】:

senderRowDeleting 中的GridView,而不是按钮,因此您的转换失败。

如果您要指定 DataKeyNames,您可以使用 GridView 的 DataKeys 属性:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" OnSelectedIndexChanged="GridView1_SelectedIndexChanged" 
             DataKeyNames = "childID"
             OnRowDeleting="GridView1_RowDeleting" >

代码隐藏:

protected void GridView1_RowDeleting(object sender, GridViewDeleteEventArgs e)
{
    string childId = GridView1.DataKeys[e.RowIndex].Value.ToString();
    string deleteSql = @"DELETE FROM Children 
                         WHERE childID = @childID;";
    using(var con = new SqlConnection(ConfigurationManager.ConnectionStrings["newregDBConnectionString"].ConnectionStr‌​ing))
    using(var cmd = new SqlCommand(deleteSql, con))
    {
        cmd.Parameters.Add("@childID", SqlDbType.VarChar).Value = childId;
        con.Open();
        int deleted = cmd.ExecuteNonQuery();
    }

    GridView1.DataSource = GetDataSource();  // provide a method that returns it
    GridView1.DataBind();
}

【讨论】:

  • 谢谢蒂姆,我正在尝试实施您的解决方案,但在 GridView1.DataSource = GetDataSource(); 行的“GetDataSource”下出现错误// 提供一个返回它的方法。我需要用什么方法替换“GetDataSource”?谢谢。
  • 好的,我意识到像上面一样,返回它的方法只是'source'
  • @ACostea:是的,我不喜欢为此使用字段,我会将它封装在一个方法中,但最后它是源代码,是的
  • 好的,我想我已经接近了,但是在按下删除时我收到了一个新错误。你能看看吗? (我已将其作为屏幕截图包含在原始问题的顶部)再次感谢蒂姆。
  • @ACostea:您应该真正熟悉调试器。在此行之前设置断点并在调试器中检查childId 的值。
【解决方案2】:

好吧,您正在处理 GridView 的删除事件,而不是按钮的单击。所以你的发送者实际上是一个 GridView 控件,你不应该将它转换为 LinkBut​​ton。

此外,您没有分配 CommandArgument。应该是这样的:

<asp:ButtonField CommandName="Delete" Text="Delete" CommandArgument='<%# Eval("childID") %>' />

但即使你这样做了,这也无济于事,因为 CommandArgument 没有与 Delete 甚至 args 一起传递。因此,您有两种选择。

首先是切换到处理RowCommand事件:

OnRowDeleting="GridView1_RowCommand"

在那里你需要检查该命令实际上是一个删除命令,并使用命令 arg 删除:

if (e.CommandName == "Delete")
{
    // parse e.CommandArgument and delete
}

其次是定义行的主键。

DataKeyNames="childID"

这将通过删除事件的事件参数提供:

e.Keys

在这种情况下,您根本不需要设置 CommandArgument。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-18
    • 2020-08-26
    • 1970-01-01
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多