使用 GridView 进行弹出窗口编辑/添加/删除记录






4.86/5 (16投票s)
使用 ModalPopupExtender 和 ConfirmButtonExtender 配合 GridView 来查看/添加/编辑数据
引言
Ajax Control Toolkit 是 Microsoft 提供的一个优秀的支持,可以与现代 Web 开发技术竞争。Ajax 的使用使 Web 应用程序访问速度更快,在与应用程序交互时提供响应能力,避免页面的完全回发,并使用部分回发来执行相关操作。下面的示例使用了服务器端控件 GridView
和 RequiredFieldValidator
,以及 Ajax 控件 UpdatePanel
、ValidatorCalloutExtender
和 ModalPopupExtender
。
背景
ASP.NET 的缺点是使用 ASP.NET 开发的 Web 应用程序比其他 Web 应用程序慢。因此,Ajax 应运而生,以解决问题并提高可用性。本示例展示了如何在实际环境中开发应用程序,以及为使 ASP.NET 网站具有更快的访问速度和良好的性能,我们应考虑哪些措施。
目标
ASP.NET 的 GridView
控件默认不提供弹出窗口编辑功能,而 Kendo-UI grid[^] 和 DevExpress grid[^] 则提供此功能,因为这些网格看起来更具交互性,并且在与网格数据交互时更方便。这种交互式网格可以通过 AjaxControlToolkit
提供的控件来开发。下面的示例使用 AjaxControlToolkit
中提供的 ModelPopupExtender
控件进行设计,通过在弹出窗口中提供编辑/添加/删除选项来扩展 GridView
的功能。
Using the Code
- 创建两个表。Emloyee 用于存储员工记录,Dept 用于存储部门相关记录,使用 SQL Server Management Studio,并使用
deptno
列建立主键-外键关系,如下所示: - 编写三个存储过程来执行数据库的添加、编辑和删除操作。
- 假设 AjaxControlToolKit.dll 已添加到项目中,并在 web.config 文件的 system.web 标记中进行了注册,如下所示:
- 在
Configuration
标记中添加一个appSettings
标记,如下所示,将UnobtrusiveValidatonMode
设置为false
: - 在 web.config 文件的
Configuration
标记中编写ConnectionString
。 - 为网站项目添加 ASP.NET 空网站模板,并将其命名为 Default.aspx。在 Default.aspx 的源视图中,写入以下代码:
- 在
head
标记中,将modalBackground
类添加到style
标记中: - 现在,在 Default.aspx 页的 form 标记中:
在 UpdatePanel 中 ->
- 添加一个
Button
控件用于添加新记录。 - 添加一个
GridView
,如下所示:<asp:GridView ID="gv" runat="server" AutoGenerateColumns="False" Width="100%" DataKeyNames="empid" BackColor="White" BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" CellPadding="4"> <Columns> <asp:TemplateField HeaderText="Edit"> <ItemTemplate> <asp:LinkButton ID="lnkEdit" Text="Edit" OnClick="lnkEdit_Click" runat="server"></asp:LinkButton> </ItemTemplate> </asp:TemplateField> <asp:TemplateField HeaderText="Delete"> <ItemTemplate> <asp:LinkButton ID="lnkDel" Text="Delete" OnClick="lnkDel_Click" runat="server"></asp:LinkButton> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="empid" HeaderText="Emp ID" /> <asp:BoundField DataField="ename" HeaderText="Name" /> <asp:BoundField DataField="job" HeaderText="Job" /> <asp:BoundField DataField="sal" HeaderText="Salary" DataFormatString="{0:N}"/> <asp:BoundField DataField="dname" HeaderText="Department" /> </Columns> </GridView>
- 添加用于显示弹出窗口的面板,以添加、删除和编辑记录,并配合
ModalPopupExtender
,如下所示:<!--Panel to add new record--> <ajaxToolkit:ModalPopupExtender ID="mpe1" runat="server" TargetControlID="btnAddNew1" PopupControlID="panelAddNew" RepositionMode="RepositionOnWindowResizeAndScroll" DropShadow="true" PopupDragHandleControlID="panelAddNewTitle" BackgroundCssClass="modalBackground" ></ajaxToolkit:ModalPopupExtender> <asp:Panel ID="panelAddNew" runat="server" style="display:none; background-color:gray;" ForeColor="Black" Width="500" Height="210"> <asp:Panel ID="panelAddNewTitle" runat="server" style="cursor:move;font-family:Tahoma;padding:2px;" HorizontalAlign="Center" BackColor="Blue" ForeColor="White" Height="25" ><b>Add New</b> </asp:Panel> <table width="100%" style="padding:5px"> <tr> <td colspan="3"> <asp:Label ID="lblStatus1" runat="server"> </asp:Label> </td> </tr> <tr> <td><b>Enter Employee Name</b></td> <td><b>:</b></td> <td><asp:TextBox ID="txtName1" runat="server"> </asp:TextBox> <asp:RequiredFieldValidator ID="rfv1" runat="server" ErrorMessage="Enter Name" Display="None" ControlToValidate="txtName1" ValidationGroup="add"> </asp:RequiredFieldValidator> <ajaxToolkit:ValidatorCalloutExtender ID="vce1" TargetControlID="rfv1" runat="server"> </ajaxToolkit:ValidatorCalloutExtender> </td> </tr> <tr> <td><b>Enter Job</b></td> <td><b>:</b></td> <td><asp:TextBox ID="txtJob1" runat="server"> </asp:TextBox> <asp:RequiredFieldValidator ID="rfv2" runat="server" ErrorMessage="Enter Job" Display="None" ControlToValidate="txtJob1" ValidationGroup="add"> </asp:RequiredFieldValidator> <ajaxToolkit:ValidatorCalloutExtender ID="vce2" runat="server" TargetControlID="rfv2" > </ajaxToolkit:ValidatorCalloutExtender> </td> </tr> <tr> <td><b>Enter Salary</b></td> <td><b>:</b></td> <td><asp:TextBox ID="txtSal1" runat="server"> </asp:TextBox> <asp:RequiredFieldValidator ID="rfv3" runat="server" ErrorMessage="Enter Salary" Display="None" ControlToValidate="txtSal1" ValidationGroup="add"> </asp:RequiredFieldValidator> <ajaxToolkit:ValidatorCalloutExtender runat="server" ID="vce3" TargetControlID="rfv3" > </ajaxToolkit:ValidatorCalloutExtender> </td> </tr> <tr> <td><b>Select Department</b></td> <td><b>:</b></td> <td><asp:DropDownList ID="ddlAdd" runat="server"> </asp:DropDownList> <asp:RequiredFieldValidator ID="rfv4" runat="server" InitialValue="0" ErrorMessage="Select Department" Display="None" ControlToValidate="ddlAdd" ValidationGroup="add"></asp:RequiredFieldValidator> <ajaxToolkit:ValidatorCalloutExtender runat="server" ID="vce4" TargetControlID="rfv4" > </ajaxToolkit:ValidatorCalloutExtender> </td> </tr> </table> <br /> <div align="center"> <asp:Button ID="btnAddNew2" runat="server" Width="70" Text="Add" OnClick="btnAddNew_Click" ValidationGroup="add"/> <asp:Button ID="btnCancel1" runat="server" Width="70" Text="Cancel" CausesValidation="false" OnClick="Cancel_Click" ValidationGroup="add"/> </div> </asp:Panel> <!--Panel to Edit record-->
与上面类似,添加用于编辑和删除记录的面板。
- 添加一个
-
现在,在 Default.aspx.cs 文件中,添加以下代码:
public partial class _Default : System.Web.UI.Page { SqlConnection cn = null; SqlDataAdapter da = null; SqlDataReader dr = null; SqlCommand cmd = null; DataSet ds = null; string sqlQry = null; protected void Page_Load(object sender, EventArgs e) { cn = new SqlConnection(); cn.ConnectionString = ConfigurationManager.ConnectionStrings["conStr"].ConnectionString; if (!Page.IsPostBack) { Bind_Data(); Bind_Data_Ddl(ddlAdd); Bind_Data_Ddl(ddlEdit); } } void Bind_Data_Ddl(DropDownList ddl) //Binding Data to DropdownLists { sqlQry = "select deptno,dname from dept"; da = new SqlDataAdapter(sqlQry, cn); ds = new DataSet(); da.Fill(ds, "dept"); ddl.DataSource = ds.Tables["dept"]; ddl.DataTextField = "dname"; ddl.DataValueField = "deptno"; ddl.DataBind(); ddl.Items.Insert(0,new ListItem ("Select","0")); } void Bind_Data() //Binding Data to GridView { sqlQry = "select e.empid,e.ename,e.job,e.sal, d.dname from employee e,dept d where e.deptno=d.deptno"; da = new SqlDataAdapter(sqlQry, cn); ds = new DataSet(); da.Fill(ds, "emp"); gv.DataSource = ds; gv.DataMember = "emp"; gv.DataBind(); } void End_Block(Panel p) //Clearing TextBoxes and DropdownLists { foreach (dynamic txtBox in p.Controls) { if(txtBox is TextBox) txtBox.Text = String.Empty; } ddlEdit.ClearSelection(); ddlAdd.ClearSelection(); mpe1.Hide(); mpe2.Hide(); mpe3.Hide(); } //Code to add new record in database protected void btnAddNew_Click(object sender, EventArgs e) { try { if (cn.State != ConnectionState.Open) cn.Open(); cmd = new SqlCommand(); cmd.CommandText = "prcAddEmployee"; cmd.Connection = cn; cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@tename", txtName1.Text); cmd.Parameters.AddWithValue("@tjob", txtJob1.Text); cmd.Parameters.AddWithValue("@tsal", txtSal1.Text); cmd.Parameters.AddWithValue("@tdeptno", ddlAdd.SelectedValue); cmd.ExecuteNonQuery(); mpe1.Hide(); } catch(SqlException e) { lblStatus1.Text = "Record is not added"; mpe1.Show(); } finally { Bind_Data(); cmd.Dispose(); cn.Close(); } } protected void Cancel1_Click(object sender, EventArgs e) { End_Block(panelAddNew); } //Code to edit existing record in database protected void lnkEdit_Click(object sender, EventArgs e) { try { LinkButton lnk = sender as LinkButton; GridViewRow gr = (GridViewRow)lnk.NamingContainer; string tempID = gv.DataKeys[gr.RowIndex].Value.ToString(); ViewState["tempId"] = tempID; sqlQry = "select ename,job,sal, deptno from employee where empid=" + tempID; if (cn.State != ConnectionState.Open) cn.Open(); cmd = new SqlCommand(sqlQry, cn); dr = cmd.ExecuteReader(); if (dr.Read()) { txtName2.Text = dr["ename"].ToString(); txtJob2.Text = dr["job"].ToString(); txtSal2.Text = dr["sal"].ToString(); ddlEdit.SelectedIndex = ddlEdit.Items.IndexOf (ddlEdit.Items.FindByValue(dr["deptno"].ToString())); } mpe2.Show(); } catch(SqlException e) { return; } finally { cmd.Dispose(); dr.Close(); cn.Close(); } } protected void btnUpdate_Click(object sender, EventArgs e) { try { if (cn.State != ConnectionState.Open) cn.Open(); cmd = new SqlCommand(); cmd.CommandText = "prcUpdateEmployee"; cmd.Connection = cn; cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@tempid", Convert.ToInt16(ViewState["tempId"].ToString())); cmd.Parameters.AddWithValue("@tename", txtName2.Text); cmd.Parameters.AddWithValue("@tjob", txtJob2.Text); cmd.Parameters.AddWithValue("@tsal", txtSal2.Text); cmd.Parameters.AddWithValue("@tdeptno", ddlEdit.SelectedValue); cmd.ExecuteNonQuery(); } catch(SqlException e) { lblStatus2.Text = "Record is not updated"; mpe2.Show(); } finally { Bind_Data(); cmd.Dispose(); cn.Close(); } } protected void Cancel2_Click(object sender, EventArgs e) { End_Block(panelEdit); } //Code to delete record from database protected void lnkDel_Click(object sender, EventArgs e) { try { LinkButton lnk = sender as LinkButton; GridViewRow gr = (GridViewRow)lnk.NamingContainer; string tempID = gv.DataKeys[gr.RowIndex].Value.ToString(); ViewState["tempId"] = tempID; sqlQry = "select empid from employee where empid=" + tempID; if (cn.State != ConnectionState.Open) cn.Open(); cmd = new SqlCommand(sqlQry, cn); dr = cmd.ExecuteReader(); if (dr.Read()) { lblId.Text = dr.GetValue(0).ToString(); } mpe3.Show(); } catch(SqlException e) { return; } finally { cmd.Dispose(); dr.Close(); cn.Close(); } } protected void btnDelete_Click(object sender, EventArgs e) { try { if (cn.State != ConnectionState.Open) cn.Open(); cmd = new SqlCommand(); cmd.CommandText = "prcDeleteEmployee"; cmd.Connection = cn; cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@tempid", Convert.ToInt16(ViewState["tempId"].ToString())); cmd.ExecuteNonQuery(); mpe3.Hide(); } catch(SqlException e) { lblStatus3.Text = "Record not deleted"; mpe3.Show(); } finally { Bind_Data(); cmd.Dispose(); cn.Close(); } } }
运行项目以查看输出。
Employee
表包含用于存储 empid
、ename
、job
、salary
和 deptno
的列。
Dept
表包含用于存储 deptno
和 dname
(部门名称)的列。
<pages>
<controls>
<add tagPrefix="ajaxToolkit" assembly="AjaxControlToolkit" namespace="AjaxControlToolkit"/>
</controls>
</pages>
<appSettings>
<add key="ValidationSettings:UnobtrusiveValidationMode" value="none"/>
</appSettings>
<head runat="server">
<style type="text/css">
.modalBackground {
background-color:silver;
opacity:0.7;
}
</style>
</head>
添加上述 CSS 类是为了与 ModalPopupExtender
的 BackgroundCssClass
属性一起使用。在弹出窗口显示时,它将为网页应用一种略带黑色的效果。
理解此示例中使用的控件
Control | ID | 描述 |
GridView | gv | 以网格格式显示记录。 |
ModalPopupExtender | mpe1 , mpe2 , mpe3 | mpe1 用于添加新记录,mpe2 用于编辑现有记录,mpe3 用于删除选定的记录。 |
RequiredFieldValidator(必填字段验证器) | rfv1 至 rfv8 | 验证 Web 应用程序中的 TextBoxes 和 DropdownList 。 |
ValidatorCalloutExtender | vce1 至 vce2 | 扩展 RequiredFieldValidators 以增强默认功能。 |
Panel | panelAddNew , panelEdit , panelDelete | 添加了 panelAddNew 、panelEdit 和 panelDelete 来显示弹出窗口,以执行添加、编辑和删除操作。 |
Button | btnDummy1 , btnDummy2 | 用于 ModalPopupExtender 的 TargetContolID 属性,因为 Linkbuttons 是 GridView 的子控件,不能用于 ModalPopupExtender 的 TargetContolID 属性。 |
注意:ModalPopupExtender
和 Panel
控件可以在 GridView
的 ItemTemplate
中使用,但问题是所有这些控件都会为 GridView
中的每个记录重复。因此,为了避免这种不必要的重复,这些控件被放在了 GridView
的外部。
输出窗口
Default.aspx 网页
用于添加新记录的网页
用于编辑现有记录的网页
用于删除记录的网页
关注点
在实现此示例时考虑的措施如下:
- 使用 AjaxControlToolKit 控件,使 Web 应用程序更快速、更具交互性和响应性。
- 使用存储过程来避免 SQL 注入攻击。
- 将
ConnectionStrings
写入 web.config 文件,以便使用ConfigurationManager
类在项目中的任何地方访问。