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

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

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

图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);
//............................................
}
}
</div>
对每行而言,编程引用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 (productID
您可能想查找下面的文章:
- ASP.NET GridView的Bootstrap分页样式
- asp.net实现固定GridView标题栏的方法(冻结列功能)
- 在ASP.NET 2.0中操作数据之六十四:GridView批量添加数据
- 在ASP.NET 2.0中操作数据之六十三:GridView实现批量删除数据
- 在ASP.NET 2.0中操作数据之六十二:GridView批量更新数据
- 在ASP.NET 2.0中操作数据之五十一:从GridView的页脚插入新记录
- 在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton
- 在ASP.NET 2.0中操作数据之二十八:GridView里的Button
- 在ASP.NET 2.0中操作数据之十五:在GridView的页脚中显示统计信息
- 在ASP.NET 2.0中操作数据之十二:在GridView控件中使用TemplateField

