DataGrid常见解决方案(三)--在DataGrid中选择,确认,删除多行复选框列表

datagrid|复选框|解决

在DataGrid中选择,确认,删除多行复选框列表

Selecting, Confirming & Deleting Multiple Checkbox Items In A DataGrid (i.e. HotMail & Yahoo)

Introduction

Although I don't have either a Hotmail or Yahoo email account, I do have friends that do, and I have often seen them check their e-mail and noticed how it was all neatly displayed in a table. Right next to each item in their e-mail table was a simple little checkbox. At the bottom or top of this table you would have another checkbox giving them the ability to select all of the e-mail, and a button to submit back. Once this was done they would receive a nice popup alert to confirm what's about to happen, and then once this is OK' ed, boom, all the selected items are deleted.

.NET, of course, has the DataGrid, their finest and most popular control to date, and it should be pretty easy to get the same functionality, right? Well, not quite. Doing this with .NET is not that straightforward and functional as I would've liked it to be. Sure it's quite easy to add an edit / update button or link to each row and even a delete button to each, alongside a pop up alert as well! However, applying this delete feature to each and every button and deleting them one by one is a little maddening. Nor is the DataGrid set up in allowing a way of adding a main "select all" checkbox to easily select all of the boxes, and then applying any particular action.

In this article, we will examine how to create a fully functional DataGrid with all the features you'd find set up on Hotmail or Yahoo. As an added bonus we'll be performing all of our data tasks strictly utilizing Microsoft's new Data Access Application Block or DAAB v2. To any who may feel a little behind with DAAB, have no fear, everything here can still be accomplished with pre-DAAB data objects as the only difference here is the data access part of it. Trust me there is a huge difference between the two, for one DAAB enable you to write about 75% less code that you would normally need when compared with regular ADO.NET!

So, before we begin, download the DAAB dll from the above link, install it, and copy it into you application’s bin folder and you're ready to go. Also, be sure and take a peek at the DAAB documentation that came with your installation for an overview and any questions you may have.

Ok, let's get to it then.

Our fully-featured DataGrid

Selecting & deleting multiple items will definitely be set up quite differently than any other type of .NET DataGrid deleting you probably have seen. However, we'll still follow the same logical flow of deletion, and we'll still confirm any delete actions about to take place after we have selected all our items. Much of the magic in making this work is really going to come from client-side JavaScript, that is ultimately responsible for wiring up our main "select all" checkbox to handle the selecting and deselecting of our checkboxes. Also, included is our server-side delete method that erases our data, and a DataGrid refresher method to rebind our DataGrid after we have completed our data deletion.

Have a look at Figure 1 to get an idea of what your DataGrid will look like:

Figure 1

Here is the code to set up our DataGrid:

<form runat="server">
<h3>Selecting, Confirming & Deleting Multiple Checkbox Items In A DataGrid (i.e. HotMail & Yahoo)</h3>
<br>

<ASP:DataGrid id="MyDataGrid" runat="server"
Width="700"
BackColor="white"
BorderColor="black"
CellPadding=3
CellSpacing="0"
Font-Size="9pt"
AutoGenerateColumns="False"
HeaderStyle-BackColor="darkred"
HeaderStyle-ForeColor="white"
>

<Columns>

<asp:TemplateColumn>

<HeaderTemplate>
<asp:CheckBox ID="CheckAll" OnClick="javascript: return select_deselectAll (this.checked, this.id);" runat="server"/>
<font face="Webdings" color="white" size="4">a</font>
</HeaderTemplate>

<ItemTemplate>
<asp:CheckBox ID="DeleteThis" OnClick="javascript: return select_deselectAll (this.checked, this.id);" runat="server"/>
</ItemTemplate>

</asp:TemplateColumn>

// ... Rest of our Custom Template & Bound Columns

</Columns>

</form>

The code listed above is what makes our DataGrid set up behave just like the grids on Hotmail and Yahoo. Our .NET DataGrid will have the same functionality and options available for selecting however many items, or perhaps all, that you'd like to delete, and once you do and submit, kiss them goodbye.

DataGrid Setup

The first step towards creating this functionality is to begin by adding a new DataGrid column (either before or after our main data, it doesn't matter) that'll contain our individual checkboxes, but also include our main top "select all" checkbox (if and when we need to select and deselect all the checkboxes below it). To do this we first make sure our DataGrid's AutoGenerateColumns property is set to false, since we're going to create the necessary custom Header and Item Templates, alongside our necessary BoundColumns, within our DataGrid Columns section (that can be customized and could contain whatever you need them to).

The only important thing to notice here, regarding our objective, is our first TemplateColumn that contains our checkboxes. The main focal point with this whole application rests solely on this first Template Column and its two Sub Templates: HeaderTemplate and ItemTemplate. Each contain the necessary checkboxes, both are wired to onClick events that executes select_deselectAll (our super-slick client-side JavaScript method) when either checkbox is checked, and in turn are fully responsible for giving us all the great functionality I've spoken of. Incidentally, the WebDings font's lowercase letter "a" give us our check symbol.

Selecting and De-Selecting our Checkboxes

Now that both checkboxes are wired to our multi-faceted JavaScript method, how is that one function going to determine the checkbox its dealing with, and the action it needs to carry out? Ah, here's how :-)

Our function select_deselectAll, listed below, accepts two arguments: the Checkbox's checked value, and its ID. Once this function is called, and its two arguments have been passed in, it'll begin looping through our form. Next, it begins performing some conditional checking utilizing JavaScript's indexOf method to locate the appropriate checkbox, and is based on both the values passed in, which it turn ultimately will give us one of several causes and effects:

If the main "select all" checkbox is checked, it will select all of the DataGrid checkboxes
If the main "select all" checkbox is unchecked, then all of the DataGrid checkboxes get unselected
Finally, if after the main "select all" checkbox is selected and all of the DataGrid's checkboxes are all checked, any one of those checkboxes gets unchecked, then the main checkbox is also unchecked. This way we don't end up having our checkbox's logic behaving inconsistently or erratically.

function select_deselectAll (chkVal, idVal) {
var frm = document.forms[0];

// Loop through all elements
for (i=0; i<frm.length; i++) {

// Look for our Header Template's Checkbox
if (idVal.indexOf ('CheckAll') != -1) {

// Check if main checkbox is checked, then select or deselect datagrid checkboxes
if(chkVal == true) {

frm.elements[i].checked = true;

} else {

frm.elements[i].checked = false;

}

// Work here with the Item Template's multiple checkboxes
} else if (idVal.indexOf ('DeleteThis') != -1) {

// Check if any of the checkboxes are not checked, and then uncheck top select all checkbox
if(frm.elements[i].checked == false) {

frm.elements[1].checked = false; //Uncheck main select all checkbox

}

}

}

}

Figure 2 shows you the effect of the JavaScript above interacting with the DataGrid when selecting the top main "select all" checkbox.

Figure 2

Now, aside from this function allowing a quick full selection, you also have the option of manually selecting as many checkbox items as you wish. Next comes the tricky part in how to determine which ones were selected, and how to confirm this the instant you submit the form, and prior to actual deletion.

Confirming Multiple Deletes

In this section, we'll examine how to confirm multiple deletes when we submit our form. Below in Figure 3 you can now see the alert confirmation after selecting a couple of items, and then submitting the form by press the "Delete Items" button. The alert takes place at any time you submit the form (as long as you have more than one checkbox selected).

Figure 3

Note that this confirmation will alert with all checkboxes selected or a just a few as shown. Pressing the Delete Items button with none selected will not prompt any alert. Here now is how we determine what checkboxes are actually checked.

The first thing we did was set up our Delete Button at the end of our DataGrid; just a regular asp server button. We also wired a server-side event to it - Delete Store - that, when confirmed, will delete the records:

<asp:Button Text="Delete Items" OnClick="DeleteStore" ID="Confirm" runat="server" />

But how does that pop-up alert confirmation appear? Well, that's the cool thing. We get this by adding the code listed below to our Button server control as soon as the page loads, in our Page_Load method, by locating it using the FindControl method and then adding to the button attributes, like so:

WebControl button = (WebControl) Page.FindControl("Confirm");
button.Attributes.Add ("onclick", "return confirmDelete (this.form);");

So, the second the page loads, it attached the Javascript handler to this button, and if you examine the HTML source code, the button afterwords, actually looks like this:

<input type="submit" name="Confirm" value="Delete Items" id="Confirm" onclick="return confirmDelete (this.form);" />

Cool huh? Now, the second this button is pressed, is when it can now trigger the client side JavaScript function below:

function confirmDelete (frm) {
// loop through all elements
for (i=0; i<frm.length; i++) {

// Look for our checkboxes only
if (frm.elements[i].name.indexOf('DeleteThis') !=-1) {

// If any are checked then confirm alert, otherwise nothing happens
if(frm.elements[i].checked) {

return confirm ('Are you sure you want to delete your selection(s)?')

}

}

}

}

Ok, what happening here? Well, the JS function above is, for all intents and purposes, not that different from the previous JavaScript function - "select_deselectAll." Except, instead of determining if the main "select all" checkbox is checked, it actually checks to see whether if any of the DataGrid row checkboxes are checked. If so, it'll then, and only then, alert you with a confirmation to proceed onto either to delete or cancel.

Deleting Data

Now recall our asp:button above, and its default JavaScript onclick event handler attached on Page_Load. Aside from this we also notice it has another OnClick event (this one being server based) that gets raised when the button is clicked, rather pressed, that'll allow it to fire the server-side DeleteStore method to delete our data:

public void DeleteStore (Object sender, EventArgs e) {

string dgIDs = "";
bool BxsChkd = false;

foreach (DataGridItem i in MyDataGrid.Items) {

CheckBox deleteChkBxItem = (CheckBox) i.FindControl ("DeleteThis");

if (deleteChkBxItem.Checked) {

BxsChkd = true;

// Concatenate DataGrid item with comma for SQL Delete
dgIDs += ((Label) i.FindControl ("StoreID")).Text.ToString() + ",";

}

}

// Set up SQL Delete statement, using LastIndexOf to remove tail comma from string.
string deleteSQL = "DELETE from Stores WHERE stor_id IN (" + dgIDs.Substring (0, dgIDs.LastIndexOf (",")) + ")";

if (BxsChkd == true) { // Execute SQL Query only if checkboxes are checked, otherwise error occurs with initial null string

try {

SqlHelper.ExecuteNonQuery (objConnect, CommandType.Text, deleteSQL);
OutputMsg.InnerHtml += "<font size=4><b>Store information has been deleted.</b></font>";
OutputMsg.Style["color"] = "green";

} catch (SqlException err) {

OutputMsg.InnerHtml += err.Message.ToString(); //"<font size=4><b>An error occurred and the record could not be deleted</b></font>";
OutputMsg.Style["color"] = "red";

}

//Refresh data
BindData();

}

}

Since having wired the two client/server methods together, it's our JavaScript code that actually intercepts this button's call and goes first. If you confirm OK, then will the deleting server-side method execute, otherwise it'll cancel all events after that point and prevent anything from posting back.

Looking at the DeleteStore() method, you'll notice that it is actually does a few things. First, it set's up the string variable "dgIDs" that will hold all of our selected DataGrid IDs. Next, it loops through the DataGrid, and gathers all of the selected item ids that are based on the row's TemplateColumn ID, which is why I kept the ID control as a TemplateColumn and the rest BoundColumns as these types of controls do not support the ID property we need for referencing our data. After this, it will, upon verifying checked items, gather all the ids and assign them to our "dgIDs" variable, that'll be used with our SQL "deleteSQL" delete statement.

The "deleteSQL" delete statement uses the "WHERE IN" argument to perform the multiple deletes in one shot. Since we need to separate each id with a comma, you'll notice that in the loop I attach a comma after each collected item. This way we'll have all of our items clearly defined in our SQL. One problem however is that since we add on a comma after each collected item, the last one as well will include a tail-end comma and SQL won't like this. For example, once we loop through the DataGrid, gather up all of the selected items, and assign it to our delete string we could end up with something like this:

DELETE from Stores WHERE stor_id IN (2,4,6,7)

Notice the last comma; that's a no-no. To quickly and easily remedy this, we must remove the last comma, and we do this by pulling the substring we need from the "dgIDs" string using LastIndexOf (",") effectively removing the last comma, and properly formatting the delete statement for SQL, like so:

DELETE from Stores WHERE stor_id IN (2,4,6,7)

Finally, DeleteStore proceeds to execute the query against the database. Incidentally, for those wondering why I have a conditional with BxsChkd? Well it's because if I don't initially select any items, I'm returned an error on Page_Load due to our SqlHelper having nothing initialized. Therefore, by do so, our DeleteStore method will remain silent, and happily waiting in the wings until it does get the actual go ahead.

So that's the crux of our DataGrid application, and technology behind doing multiple checkbox deletes a la Hotmail and Yahoo style. And on that note, here's all the code. Just have SQL Server ready, DAAB installed, then cut and paste the code below, and have fun.

Here's our main page code:

<%@ Page Language="C#" Debug="False" Strict="True" Explicit="True" Inherits="MultiDeleteDG.WebForm" Src="mDatagrid.aspx.cs"%>

<html>
<body>

<form runat="server">

<h3>Selecting, Confirming & Deleting Multiple Checkbox Items In A DataGrid (i.e. HotMail & Yahoo)</h3>
<br>

<ASP:DataGrid id="MyDataGrid" runat="server"
Width="700"
BackColor="white"
BorderColor="black"
CellPadding=3
CellSpacing="0"
Font-Size="9pt"
AutoGenerateColumns="False"
HeaderStyle-BackColor="darkred"
HeaderStyle-ForeColor="white"
>

<Columns>

<asp:TemplateColumn>

<HeaderTemplate>
<asp:CheckBox ID="CheckAll" OnClick="javascript: return select_deselectAll (this.checked, this.id);" runat="server"/>
<font face="Webdings" color="white" size="4">a</font>
</HeaderTemplate>

<ItemTemplate>
<asp:CheckBox ID="DeleteThis" OnClick="javascript: return select_deselectAll (this.checked, this.id);" runat="server"/>
</ItemTemplate>

</asp:TemplateColumn>

<asp:TemplateColumn>

<HeaderTemplate>ID</HeaderTemplate>

<ItemTemplate>
<asp:Label ID="StoreID" Text='<%# DataBinder.Eval (Container.DataItem, "ID") %>' runat="server"/>
</ItemTemplate>

</asp:TemplateColumn>

<asp:BoundColumn HeaderText="Store" Datafield="Store" runat="server"/>

<asp:BoundColumn HeaderText="Address" Datafield="Address" runat="server"/>

<asp:BoundColumn HeaderText="City" Datafield="City" runat="server"/>

<asp:BoundColumn HeaderText="State" Datafield="State" runat="server"/>

<asp:BoundColumn HeaderText="Zip" Datafield="Zip" runat="server"/>

</Columns>

</ASP:DataGrid>

<br>

<asp:Button Text="Delete Items" OnClick="DeleteStore" ID="Confirm" runat="server" />

<span id="OutputMsg" EnableViewState="false" runat="server"/>

</form>

</body>

And our MultiDeleteDG.WebForm code-behind file - mDatagrid.aspx.cs:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
//Import DAAB dll namespace
using Microsoft.ApplicationBlocks.Data;

namespace MultiDeleteDG
{

/// <summary>
/// Selecting, Confirming & Deleting Multiple Checkbox Items In A DataGrid (i.e. HotMail & Yahoo)
/// Author: Dimitrios Markatos - dmarko1@aol.com
/// Date: 8/2003
/// </summary>

public class WebForm : System.Web.UI.Page //Inherit Page Class
{

protected System.Web.UI.WebControls.DataGrid MyDataGrid;
protected System.Web.UI.HtmlControls.HtmlGenericControl OutputMsg; //Span Tag

protected SqlConnection objConnect;

public void Page_Load (Object Sender, EventArgs E) {

//Implement Client Side JavaScript code
string jsScript = "<script language=JavaScript> \n" +
"<!--\n" +
"function confirmDelete (frm) {\n\n" +
" // loop through all elements\n" +
" for (i=0; i<frm.length; i++) {\n\n" +
" // Look for our checkboxes only\n" +
" if (frm.elements[i].name.indexOf ('DeleteThis') !=-1) {\n" +
" // If any are checked then confirm alert, otherwise nothing happens\n" +
" if(frm.elements[i].checked) {\n" +
" return confirm ('Are you sure you want to delete your selection(s)?')\n" +
" }\n" +
" }\n" +
" }\n" +
"}\n\n\n" +

"function select_deselectAll (chkVal, idVal) {\n" +
"var frm = document.forms[0];\n" +
"// loop through all elements\n" +
" for (i=0; i<frm.length; i++) {\n" +
" // // Look for our Header Template's Checkbox\n" +
" if (idVal.indexOf ('CheckAll') != -1) {\n" +
" // Check if main checkbox is checked, then select or deselect datagrid checkboxes \n" +
" if(chkVal == true) {\n" +
" frm.elements[i].checked = true;\n" +
" } else {\n" +
" frm.elements[i].checked = false;\n" +
" }\n" +
" // Work here with the Item Template's multiple checkboxes\n" +
" } else if (idVal.indexOf('DeleteThis') != -1) {\n" +
" // Check if any of the checkboxes are not checked, and then uncheck top select all checkbox\n" +
" if(frm.elements[i].checked == false) {\n" +
" frm.elements[1].checked = false; // Check if any of the checkboxes are not checked, and then uncheck top select all checkbox\n" +
" }\n" +
" }\n" +
" }\n" +
"}" +
"//--> \n" +
"</script>";

//Allows our .NET page to add client-side script blocks when page loads, instead of the conventional HTML JS tags.
RegisterClientScriptBlock ("clientScript", jsScript);

WebControl button = (WebControl) Page.FindControl ("Confirm");
button.Attributes.Add ("onclick", "return confirmDelete (this.form);");

objConnect = new SqlConnection ("server=(local);database=pubs;uid=sa;pwd=;");

if (!IsPostBack) {

BindData();

}

}

public void DeleteStore (Object sender, EventArgs e) {

string dgIDs = "";
bool BxsChkd = false;

foreach (DataGridItem i in MyDataGrid.Items) {

CheckBox deleteChkBxItem = (CheckBox) i.FindControl ("DeleteThis");

if (deleteChkBxItem.Checked) {

BxsChkd = true;

// Concatenate DataGrid item with comma for SQL Delete
dgIDs += ((Label) i.FindControl ("StoreID")).Text.ToString() + ",";

}

}

// Set up SQL Delete statement, using LastIndexOf to remove tail comma from string.
string deleteSQL = "DELETE from Stores WHERE stor_id IN (" + dgIDs.Substring (0, dgIDs.LastIndexOf (",")) + ")";

if (BxsChkd == true) { // Execute SQL Query only if checkboxes are checked, otherwise error occurs with initial null string

try {

SqlHelper.ExecuteNonQuery (objConnect, CommandType.Text, deleteSQL);
OutputMsg.InnerHtml += "<font size=4><b>Store information has been deleted.</b></font>";
OutputMsg.Style["color"] = "green";

} catch (SqlException err) {

OutputMsg.InnerHtml += err.Message.ToString(); //"<font size=4><b>An error occurred and the record could not be deleted</b></font>";
OutputMsg.Style["color"] = "red";

}

//Refresh data
BindData();

}

}

public void BindData() {

String sqlQuery = "Select stor_id As Id, stor_name As Store, City, State, Zip from Stores";

MyDataGrid.DataSource = SqlHelper.ExecuteDataset(objConnect, CommandType.Text, sqlQuery);
MyDataGrid.DataBind();

objConnect.Close();
objConnect = null;

}

} //End Class

}//End Namespace

Conclusion

Well, that's it. Pretty awesome, and there was sure a lot to grasp as this certainly was a fairly complex article; but look at what you can do with a DataGrid now? There's nothing preventing you from adding paging to it although you'll have to delete whatever you need per page before paging to the next, or you could also store all your selected values in View State or any of of state methods, then pull them from there at the end.

At any rate, .NET clearly demonstrates that its Framework and all included is simply the best once again. Period!

Until next time. Happy .NETing

时间: 2024-10-03 06:25:34

DataGrid常见解决方案(三)--在DataGrid中选择,确认,删除多行复选框列表的相关文章

javascript选择当前页面所有checkbox 复选框代码

javascript选择当前页面所有checkbox 复选框代码 <!doctype html public "-//w3c//dtd xhtml 1.0 transitional//en" "http://www.w3.org/tr/xhtml1/dtd/xhtml1-transitional.dtd"> <html xmlns="http://www.jzread.com/1999/xhtml"> <head&g

ASP.NET中CheckBoxList复选框列表控件详细使用方法_基础应用

可以使用两种类型的 ASP.NET 控件将复选框添加到 Web 窗体页上:单独的 CheckBox 控件或 CheckBoxList 控件.两种控件都为用户提供了一种输入布尔型数据(真或假.是或否)的方法. 本文主要介绍CheckBoxList,不言而喻,看到List就知道是一个列表(集合),一个控件可以包含多个CheckBox,下面让我们来看看具体的用法. 1.绑定数据 复制代码 代码如下: this.lngCatalogID.DataSource = dt; //这里我绑到DataTable

Struts的动态复选框-用动态选择的元素轻松创建复选框

简介:Struts Recipes 的合著者 Danilo Gurovich 从 George Franciscus 停止的地方开始,介绍了 易于使用的创建动态选择复选框的 Struts 诀窍. 在用户界面设计中,复选框组不如它的同类 -- 多行选择框那样流行.它们基本上做的是同一件事 ,即选择映射到单一 name 属性的一组选项.当在组中使用时,复选框执行的功能实际与多行选择框一样 ,但是它们占据的屏幕空间更多.当希望用户在选择一个或多个选项之前能够看到所有选项的时候,这会 很有好处. 虽然在

Windows 7旗舰版系统下设置文件选择时前面有个复选框的方法

  1.首先在键盘按"win+E"组合键打开资源管理器,然后点击上方的"组织--文件夹和搜索选项"项; 2.在弹出来的"文件夹选项"界面中,切换到"查看"页面,然后在高级设置框中找到并勾选"使用复选框以选择项",然后点击确定按钮保存退出; 3.接着回到文件夹中,就会发现文件或图片前面多了个复选框,这样就可以直接用√选择需要选择的文件,是不是方便多了.

在jquery repeater中添加设置日期,下拉,复选框等控件_实用技巧

如果, 有不明白的问题, 请先阅读 30 分钟掌握无刷新 Repeater. 示例代码下载: http://zsharedcode.googlecode.com/files/JQueryElementDemo.rar 本文将详细的讲解 Repeater 控件的模板中如何处理控件, 目录如下: * 准备 * html 元素 * 文本框 * 下拉框 * 多行文本框 * 复选框 * jQueryUI 插件 * jQueryUI 日期框 * jQueryUI 按钮 * jQueryUI 自动匹配 示例图

DataGrid常见解决方案(五)--- 在DataGrid产生空行纪录

datagrid|解决 在应用程序中,我需要在一个DataGrid中每显示10条纪录后便添加一个空行,我们可以简单的修改DataTable,并且在DataGrid中的ItemDataBound 事件书写一些代码来实现,下面的文章将阐述如何做到这一点. In one application I had the requirement to add a blank row after every 10 rows in a DataGrid rather than use paging as show

Delphi中为TreeView添加单选和复选框

打开电脑,进入Windows操作系统,在资源管理器的左边栏中清楚地显示了系统管理的所有磁盘的信息以及各个磁盘所容纳的文件与文件夹(如图一).这种常见的显示方式是由一个根节点和若干个子节点构成的,这被称为"树形结构".这种树形结构的用途非常广泛,在很多常用软件中都出现过它的身影.Windows中将这种结构封装为"树形控件",即TreeView控件,它与ListView.Button等一样都属于系统自带的通用公共控件.在Delphi中,TreeView也被封装成了VCL

jQuery获取复选框被选中数量及判断选择值的方法详解_jquery

本文实例讲述了jQuery获取复选框被选中数量及判断选择值的方法.分享给大家供大家参考,具体如下: 获取复选框被选中值 <input type="button" id="btn5" value="获得选中的所有值"> <input type="text" name="dd" id="dd" size="50" /> $("#btn5&

html中的checkbox复选框不确定状态的设置

 这篇经验要分享的是复选框的不确定状态的,html中的复选框是:     <input id="cb" type="checkbox"/>     一般遇到复选框或许只需要选中或者不选中两种状态即可,但是有时候需要第三种不确定状态,例如做带复选框的级联菜单时,子级菜单的多个复选框为部分选中的时,父级菜单的复选框应处于不确定状态,来反映子菜单的部分选中情况.     方法是通过js设置复选框的indeterminate属性,在标签中设置此属性无效.