在ASP.NET 2.0中操作数据之六十三:GridView实现批量删除数据

   2016-05-23 0
核心提示:本文主要介绍在GridView控件中包含一个checkbox列来实现复选多条数据,在批量删除按钮的事件中通过for循环来一一删除。

导言:

  在前面的教程,我们用GridView创建了一个批编辑界面。在用户需要一次性编辑多条记录的情况下,批编辑界面很有用。同理,当用户需要同时删除多条记录时,该技术也很有用.

  如果你使用过邮件系统的话,你应该对这种最常见的批删除界面很熟悉:界面里每一行都包含一个checkbox,此外,还有一个“Delete All Checked Items”按钮(如图1).本教程比较短,因为我们在前面的教程已经完成大体的框架,在前面的第50章《为GridView控件添加Checkbox》里我们创建了一个包含一个checkboxes列的GridView控件;而在61章《在事务里对数据库修改进行封装》里,我们在BLL业务逻辑层里创建了一个方法,该方法使用事务来删除基于ProductID 的记录.在本教程,我们将整合这些内容来创建一个处理批删除的示例.

在ASP.NET 2.0中操作数据之六十三:GridView实现批量删除数据
图1:每一行都包含一个Checkbox

第一步:创建批删除界面

  由于我们在第52章已经创建了一个批删除界面,因此我们可以简单的将其拷贝到BatchDelete.aspx页面。首先,打开BatchData文件夹里的BatchDelete.aspx页面,以及EnhancedGridView文件夹里的CheckBoxField.aspx页面。在CheckBoxField.aspx页面,切换到Source模式,将<asp:Content>标签里的代码进行复制.

在ASP.NET 2.0中操作数据之六十三:GridView实现批量删除数据
图2:复制CheckBoxField.aspx页面里的声明代码

  然后,切换到BatchDelete.aspx页面的Source模式,将代码粘贴到<asp:Content>标签里.同理,将CheckBoxField.aspx.cs里面的后台代码拷贝到BatchDelete.aspx.cs里.(具体来说,就是将DeleteSelectedProducts按钮的Click event事件、ToggleCheckState方法、CheckAll 和 UncheckAll按钮的Click event事件)。完成拷贝后,BatchDelete.aspx页面的后台代码类应该包含下面的代码:

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class BatchData_BatchDelete : System.Web.UI.Page
{
 protected void DeleteSelectedProducts_Click(object sender, EventArgs e)
 {
 bool atLeastOneRowDeleted = false;

 // Iterate through the Products.Rows property
 foreach (GridViewRow row in Products.Rows)
 {
 // Access the CheckBox
 CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
 if (cb != null && cb.Checked)
 {
 // Delete row! (Well, not really...)
 atLeastOneRowDeleted = true;

 // First, get the ProductID for the selected row
 int productID = Convert.ToInt32(Products.DataKeys[row.RowIndex].Value);

 // "Delete" the row
 DeleteResults.Text += string.Format
  ("This would have deleted ProductID {0}<br />", productID);

 //... To actually delete the product, use ...
 //ProductsBLL productAPI = new ProductsBLL();
 //productAPI.DeleteProduct(productID);
 //............................................
 }
 }

 // Show the Label if at least one row was deleted...
 DeleteResults.Visible = atLeastOneRowDeleted;
 }

 private void ToggleCheckState(bool checkState)
 {
 // Iterate through the Products.Rows property
 foreach (GridViewRow row in Products.Rows)
 {
 // Access the CheckBox
 CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
 if (cb != null)
 cb.Checked = checkState;
 }
 }

 protected void CheckAll_Click(object sender, EventArgs e)
 {
 ToggleCheckState(true);
 }

 protected void UncheckAll_Click(object sender, EventArgs e)
 {
 ToggleCheckState(false);
 }
}

  完成上述工作后,花几分钟在浏览器里测试该页面.你应该首先看到一个GridView控件列出了前10个产品,每行列出了产品的name, category,price以及一个checkbox. 同时应该有3个按钮“Check All”, “Uncheck All”和“Delete Selected Products”.点“Check All”按钮将会选中所有的checkboxes;而“Uncheck All”按钮将释放所有的
checkboxes;点“Delete Selected Products”的话将显示一个消息,列出选中的产品的ProductID值,不过并不会真的删除产品.

在ASP.NET 2.0中操作数据之六十三:GridView实现批量删除数据
图3:CheckBoxField.aspx页面的界面搬到了BatchDeleting.aspx页面

第二步:在事务里删除选中的产品

  完成界面后,剩下的事情是更新代码,以便当点击“Delete Selected Products”按钮时,使用ProductsBLL class类里的DeleteProductsWithTransaction方法来删除选中的产品.该方法是我们在第61章《在事务里对数据库修改进行封装》里添加的,它接受一系列的ProductID值,然后在一个事务里将删除对应的ProductID的记录.

DeleteSelectedProducts按钮的Click事件目前使用的foreach循环如下:

// Iterate through the Products.Rows property
foreach (GridViewRow row in Products.Rows)
{
 // Access the CheckBox
 CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
 if (cb != null && cb.Checked)
 {
 // Delete row! (Well, not really...)
 atLeastOneRowDeleted = true;

 // First, get the ProductID for the selected row
 int productID = Convert.ToInt32(Products.DataKeys[row.RowIndex].Value);

 // "Delete" the row
 DeleteResults.Text += string.Format
 ("This would have deleted ProductID {0}<br />", productID);

 //... To actually delete the product, use ...
 //ProductsBLL productAPI = new ProductsBLL();
 //productAPI.DeleteProduct(productID);
 //............................................
 }
}

  对每行而言,编程引用ProductSelector CheckBox控件,如果它被选中,从DataKeys collection集获取该产品的ProductID值,然后更新DeleteResults控件的Text属性以显示要删除该行.

  上面的代码并不会真的删除任何的记录,因为在ProductsBLL class类里我们只是注释出了如何使用Delete方法。 不过就算实际地运用了这些删除逻辑,这些代码虽然可以删除产品但没有运用原子操作.也就是说,如果按顺序对头几个产品删除成功,如果接下来的某个产品删除失败(比如可能是违背里外键约束),那么将抛出一个异常,但是前面的删除操作并不会回滚.

  为了保证使用原子操作,我们将转为使用ProductsBLLclass类的DeleteProductsWithTransaction method方法.由于该方法接受一系列的ProductID值,
我们首先需要编译这一系列的值,再将其作为参数传递出去.我们首先创建一个int类型的List<T>的实例,在foreach循环里我们需要将产品的ProductID值添加给List<T>,结束循环后,List<T>将传递给ProductsBLL class类的DeleteProductsWithTransaction method方法,用下面的代码对DeleteSelectedProducts按钮的Click事件处理器进行更新:

protected void DeleteSelectedProducts_Click(object sender, EventArgs e)
{
 // Create a List to hold the ProductID values to delete
 System.Collections.Generic.List<int> productIDsToDelete =
 new System.Collections.Generic.List<int>();

 // Iterate through the Products.Rows property
 foreach (GridViewRow row in Products.Rows)
 {
 // Access the CheckBox
 CheckBox cb = (CheckBox)row.FindControl("ProductSelector");
 if (cb != null && cb.Checked)
 {
 // Save the ProductID value for deletion
 // First, get the ProductID for the selected row
 int productID = Convert.ToInt32(Products.DataKeys[row.RowIndex].Value);

 // Add it to the List...
 productIDsToDelete.Add(productID);

 // Add a confirmation message
 DeleteResults.Text += string.Format
 ("ProductID {0} has been deleted<br />", productID);
 }
 }

 // Call the DeleteProductsWithTransaction method and show the Label
 // if at least one row was deleted...
 if (productIDsToDelete.Count > 0)
 {
 ProductsBLL productAPI = new ProductsBLL();
 productAPI.DeleteProductsWithTransaction(productIDsToDelete);

 DeleteResults.Visible = true;

 // Rebind the data to the GridView
 Products.DataBind();
 }
}

  上述代码创建了一个int类型的List<T>(也就是productIDsToDelete),并用ProductID值对其进行填充,foreach循环结束后,如果至少选中了一个产品,将调用ProductsBLL 类的DeleteProductsWithTransaction method方法,并传递该List。名为DeleteResults的Label控件也将显示出来;数据重新绑定到GridView(自然,刚删除掉的记录将不会显示出来).

图4里,我们选择几个产品以删除;图5显示的是点击“Delete Selected Products”按钮后的界面.注意,在Label控件里显示的已经删除的产品的ProductID值,而这些产品已经删除掉了,并没有出现在GridView控件里.

在ASP.NET 2.0中操作数据之六十三:GridView实现批量删除数据
图4:选中的产品将被删除

在ASP.NET 2.0中操作数据之六十三:GridView实现批量删除数据
图5:被删除产品的ProductID值出现的GridView下面的Label控件里

  注意:为验证DeleteProductsWithTransaction method方法的原子操作,你可以为某个产品在Order Details表里手动添加一个条目,然后尝试删除该产品(当然与其它产品一起删除).这将会违背外键约束,注意对其它产品的删除操作是如何回滚的.

总结:

  创建一个批删除界面的话,我们需要创建一个包含checkboxes列的GridView控件,以及Button Web控件。当点击该按钮时,我们将删除多个产品当作一个单一原子操作.在本文,我们创建的界面整合了以前的2个章节的内容.

  在下一篇,我们考察如何创建一个批插入的界面

  祝编程快乐!

作者简介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的书,是4GuysFromRolla.com的创始人,自1998年以来一直应用 微软Web技术。大家可以点击查看全部教程《[翻译]Scott Mitchell 的ASP.NET 2.0数据教程》,希望对大家的学习ASP.NET有所帮助。

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • [VB][ASP.NET]FileUpload控件「批次上传 / 多档
    FileUpload控件「批次上传 / 多档案同时上传」的范例 (VB语法) http://www.dotblogs.com.tw/mis2000lab/archive/2008/05/14/3986.aspx    FileUpload控件真的简单好用,不使用它来作批次上传,却要改用别的方法,实在不聪明。要用就一次用到底,公开File
    02-10
  • 使用WebClient自动填写并提交ASP.NET页面表单的源代码
    使用WebClient自动填写并提交ASP.NET页面表单的
    转自:http://www.cnblogs.com/anjou/archive/2007/03/07/667253.html 在.NET中通过程序填写和提交表单还是比较简单。比如,要提交一个如下图所示的登录表单:           填写和提交以上表单的代码如下:       // 要提交表单的URI字符串
    02-09
  • asp.net mvc多条件+分页查询解决方案
    


            
asp.net mvc多条件+分页查询解决方案
    asp.net mvc多条件+分页查询解决方案
    http://www.cnblogs.com/nickppa/p/3232535.html开发环境vs2010css:bootstrapjs:jquery    bootstrap paginator原先只是想做个mvc的分页,但是一般的数据展现都需要检索条件,而且是多个条件,所以就变成了MVC多条件+分页查询因为美工不是很好,所以用的是
    02-09
  • ASP.NET操作Cookies的问题(Bug or Not)
    以下存和取都是在不同的页面中,如果是在同一个页面也没必要用cookies了。 Test1: 给Cookies赋值: const string AAA="aaa"; Response.Cookies[AAA].Value = "111;222;333"; 取值: string value = Request.Cookies[AAA].Value; // value为111 Test2: 给Cooki
    02-09
  • Asp.Net Core 自定义验证属性
      很多时候,在模型上的验证需要自己定义一些特定于我们需求的验证属性。所以这一篇我们就来介绍一下怎么自定义验证属性。  我们来实现一个验证邮箱域名的自定义验证属性,当然,最重要的是需要定义一个继承自ValidationAttribute的类,然后在实现其IsVal
    02-09
  • Asp.Net 之 枚举类型的下拉列表绑定
    有这样一个学科枚举类型:/// 学科 /// /summary public enum Subject {None = 0,[Description("语文")]Chinese = 1,[Description("数学")]Mathematics = 2,[Description("英语")]English = 3,[Description("政治")]Politics = 4,[Description("物理&qu
    02-09
  • [ASP.NET笔记] 1.Web基础知识
         1:http协议:     2:web服务器:     3:静态网页的概念     4:动态网页的概念       http协议:http(hypertext transfer protocol) 即超文本传输协议,这个协议是在internet上进行信息传送的协议任何网页之间要相互沟通,必须要尊循
    02-09
  • ASP.NET邮件发送 .net 发送邮件
      今天做了个ASP.NET做发送邮件功能,发现QQ邮箱好奇怪,当你用QQ邮箱做服务器的时候什么邮件都发送不出去(QQ邮箱除外)。而且爆出这样的错误:"邮箱不可用。 服务器响应为: Error: content rejected.http://mail.qq.com/zh_CN/help/content/rejectedmail.ht
    02-09
  • 由ASP.NET Core根据路径下载文件异常引发的探究
    前言    最近在开发新的项目,使用的是ASP.NET Core6.0版本的框架。由于项目中存在文件下载功能,没有使用类似MinIO或OSS之类的分布式文件系统,而是下载本地文件,也就是根据本地文件路径进行下载。这其中遇到了一个问题,是关于如何提供文件路径的,通
    02-09
  • ASP.NET的运行原理与运行机制 ASP.NET的开发模式包括
    ASP.NET的运行原理与运行机制 ASP.NET的开发模
    在Asp.net4和4.5中,新增了WebPages Framework,编写页面代码使用了新的Razor语法,代码更加的简洁和符合Web标准,编写方式更接近于PHP和以前的Asp,和使用WebForms这种模仿Windows Form编程方式有了很大不同,不再有大量控件和控件生成的大量不够灵活的代码
    02-09
点击排行