生活就好像一盒巧克力

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

dataGrid 中添加数据

原文:dataGrid 中添加数据
文件代码:
test.aspx
===========================>
<%@ Page Language="C#" Debug="True"%>
<%@Import Namespace="System.Data"%>
<%@ Import Namespace="System.Data.SqlClient" %>

<script language="C#" runat="server">
const string DataTableName="Employees";
SqlConnection conn;
SqlDataAdapter adapter;
void Page_Load(Object src, EventArgs e)
{
conn=new SqlConnection("server=(local);database=pubs;uid=sa;pwd=");
adapter=new SqlDataAdapter("select * from employees",conn);
if(!Page.IsPostBack){
BindData();
}
}

//绑定数据
void BindData(){
//先从Session中获取DataTable
DataTable table=(DataTable)Session[DataTableName];
//若Session中的DataTable不存在,则从数据库获取数据
if(table==null){
table=new DataTable();
adapter.Fill(table);
//将DataTable保存到Session中
SaveTableToSession(table);
table.Columns["id"].AutoIncrement=true;
}
grid.DataSource=table;
grid.DataBind();
}

void ChangePage(object src,DataGridPageChangedEventArgs e){
grid.CurrentPageIndex=e.NewPageIndex;
BindData();
}

void UpdateDataTable(object src,EventArgs e){
try{
DataTable table=GetTableFromSession();
string name;
byte age;
string address;
CheckBox ckdel;
for(int i=0;i<grid.Items.Count;i++){
DataGridItem dgitem=grid.Items[i];
int empId=(int)grid.DataKeys[dgitem.ItemIndex];
ckdel=dgitem.FindControl("delckb") as CheckBox;
name=((TextBox)dgitem.Cells[0].Controls[1]).Text;
age=byte.Parse(((TextBox)dgitem.Cells[1].Controls[1]).Text);
address=((TextBox)dgitem.Cells[2].Controls[1]).Text;
UpdateEmployee(table,empId,name,age,address,ckdel.Checked);
}
SaveTableToSession(table);
cancelbtn.Enabled=true;
int rowcount=0;
foreach(DataRow row in table.Rows){
if(row.RowState!=DataRowState.Deleted)
rowcount++;
}
if(Math.Ceiling(rowcount/5.0)==grid.CurrentPageIndex&&grid.CurrentPageIndex>0)
grid.CurrentPageIndex-=1;
BindData();
msglbl.Text="更新数据表成功!";
}
catch(Exception ex){
msglbl.Text="更新数据表失败,出现意外错误:"+ex.Message;
}
}


void UpdateEmployee(DataTable table,int id,string name,byte age,string address,bool isDelete){
for(int i=0;i<table.Rows.Count;i++){
DataRow row=table.Rows[i];
//如果选中了删除复选框,就直接就该行数据删除,不用再更新,否则更新该行数据
if(row!=null&&row.RowState!=DataRowState.Deleted){
if((int)row["id"]==id){
if(!isDelete){
row["name"]=name;
row["age"]=age;
row["address"]=address;
}
else
row.Delete();
}
}
}
msglbl.Text="更新数据表成功!";
}

void UpdateDataBase(object src,EventArgs e){
try{
DataTable table=GetTableFromSession();
SqlCommandBuilder cmdbd=new SqlCommandBuilder(adapter);
adapter.Update(table);
msglbl.Text="更新数据源成功!";
cancelbtn.Enabled=false;
}
catch(Exception ex){
msglbl.Text="更新数据源失败,出现意外错误:"+ex.Message;
}
BindData();
}

void CancelUpdate(object src,EventArgs e){
DataTable table=GetTableFromSession();
table.RejectChanges();
grid.CurrentPageIndex=0;
BindData();
cancelbtn.Enabled=false;
}

void AddNewEmployee(object src,DataGridCommandEventArgs e){
if(e.CommandName=="Add"){
try{
DataTable table=GetTableFromSession();
string name=((TextBox)e.Item.FindControl("newname")).Text;
byte age=byte.Parse(((TextBox)e.Item.FindControl("newage")).Text);
string address=((TextBox)e.Item.FindControl("newaddress")).Text;
DataRow row=table.NewRow();
row["name"]=name;
row["age"]=age;
row["address"]=address;
table.Rows.Add(row);
SaveTableToSession(table);
//重新绑定数据
BindData();
msglbl.Text="添加新记录成功!";
cancelbtn.Enabled=true;
}
catch(Exception ex){
msglbl.Text="未能添加新记录,出现意外错误:"+ex.Message;
}
}
}

//将DataTable保存到session中
void SaveTableToSession(DataTable table){
Session[DataTableName]=table;
}

//从Session中获取DataTable
DataTable GetTableFromSession(){
DataTable table=(DataTable)Session[DataTableName];
if(table!=null){
return table;
}
else{
msglbl.Text="未能从Session中获取数据,可能Session已超时,请刷新或重新打开当前页面!";
return null;
}
}
</script>
<html>
<head>
<title> Webdiyer制造:)</title>
<META NAME="Generator" CONTENT="EditPlus">
<META NAME="Author" CONTENT="Webdiyer(http://www.webdiyer.com)">
</head>
<body>

<form runat="server">
<asp:DataGrid runat="server" id="grid" AutogenerateColumns=false DataKeyField="id" ShowFooter=true AllowPaging=true PageSize=5 OnPageIndexChanged="ChangePage" PagerStyle-Mode="numericpages" OnItemCommand="AddNewEmployee">
<Columns>
<asp:TemplateColumn HeaderText="姓名">
<ItemTemplate>
<asp:TextBox runat="server" id="name" Text='<%#DataBinder.Eval(Container.DataItem,"name")%>'/>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox runat="server" id="newname"/>
</FooterTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="年龄">
<ItemTemplate>
<asp:TextBox runat="server" id="age" Text='<%#DataBinder.Eval(Container.DataItem,"age")%>'/>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox runat="server" id="newage"/>
</FooterTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="住址">
<ItemTemplate>
<asp:TextBox runat="server" id="address" Text='<%#DataBinder.Eval(Container.DataItem,"address")%>'/>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox runat="server" id="newaddress"/>
</FooterTemplate>
</asp:TemplateColumn>
<asp:TemplateColumn HeaderText="删除">
<ItemTemplate>
<asp:CheckBox runat="server" id="delckb"/>
</ItemTemplate>
<FooterTemplate>
<asp:Button runat="server" Text="添加" CommandName="Add"/>
</FooterTemplate>
</asp:TemplateColumn>
</Columns>
</asp:DataGrid>
<asp:Label runat="server" EnableViewState="false" id="msglbl" ForeColor="red"/>
<div>
<asp:Button runat="server" id="updatebtn" Text="更新数据表" OnClick="UpdateDataTable"/>
<asp:Button runat="server" id="cancelbtn" Text="取消对数据表的更新" Enabled=false OnClick="CancelUpdate"/>
<asp:Button runat="server" id="updatedbtbn" Text="更新数据源" OnClick="UpdateDataBase"/>
</div>
<div>
说明:DataGrid中的数据类型都没有进行验证,如果输入错误的数据类型或空值可能会出错,实际应用中应该对用户输入的数据进行验证!
</div>
</form>

</body>
</html>


数据库中employees表结构:

CREATE TABLE employees (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[name] [nvarchar] (10) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[age] [tinyint] NOT NULL ,
[address] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL
) ON [PRIMARY]
GO

ALTER TABLE employees ADD
CONSTRAINT [PK_employees] PRIMARY KEY CLUSTERED
(
[id]
) ON [PRIMARY]
GO




CNBIE BLOG

Datagrid 链接数据库Access

原文:Datagrid 链接数据库Access

<%@ Import Namespace="System" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.OleDb" %>
<script Language="c#" runat="server">
  void Page_Load()
  {
    string strConnection = "Provider=Microsoft.Jet.OleDb.4.0;";
    strConnection += @"Data Source=\genfs1www11etningxmlNorthwind.mdb";
    string strSQL = "SELECT * FROM Employees ";
    DataSet objDataSet = new DataSet();
    OleDbConnection objConnection = new OleDbConnection(strConnection);
    OleDbDataAdapter objAdapter = new OleDbDataAdapter(strSQL, objConnection);
    objAdapter.Fill(objDataSet, "Employees");
    DataView objDataView = new DataView(objDataSet.Tables["Employees"]);
    dgNameList.DataSource=objDataView;
    dgNameList.DataBind();
  }

</script>
<html>
  <body>
<h4><%=Request.QueryString["id"]%></h4>

  <asp:datagrid id="dgNameList" runat="server"
    BackColor="#ffffff"
    CellPadding=2
    CellSpacing="0"
    ShowFooter="true"
    Font-Name="???I"
    Font-Size="10pt"
    HeaderStyle-BackColor="#eeaadd"
    EnableViewState="false"
    AutoGenerateColumns="false"
    AllowCustomPaging="false"
    >
<HeaderStyle BackColor="#00eeaa"></HeaderStyle>
<FooterStyle BackColor="#aaaadd"></FooterStyle>
<PagerStyle Mode="NumericPages" HorizontalAlign="Right"></PagerStyle>
<SelectedItemStyle BackColor="blue"></SelectedItemStyle>
<ItemStyle BackColor="#ffffee"></ItemStyle>
<AlternatingItemStyle BackColor="#6699ff"></AlternatingItemStyle>
         <Columns>
           
            <asp:HyperLinkColumn
                 HeaderText="Title"
                 DataNavigateUrlField="Title"
                 DataNavigateUrlFormatString="datareadasp.aspx?id={0}"
                 DataTextField="Title"
                 DataTextFormatString="{0:c}"
                 />
         </Columns>
</ASP:DataGrid>
</body>
</html>



CNBIE BLOG

datagrid编辑、修改、删除、翻页例子

原文:datagrid编辑、修改、删除、翻页例子
 现在数据库中建立test表,字段分别为ID、Code、Name;

数据库的链接这里就不具体写了,数据库的链接和操作请求我写在了AreaInfo.cs中,代码中会用到,这里声明一下

<%@ Page language="c#" Codebehind="Update.aspx.cs" AutoEventWireup="false" Inherits="Client.Page.AreaInfo.Update" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
 <HEAD>
  <title>test</title>
  <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
  <meta name="CODE_LANGUAGE" Content="C#">
  <meta name="vs_defaultClientScript" content="JavaScript">
  <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
 </HEAD>
 <body MS_POSITIONING="GridLayout" bgcolor="ivory">
  <font face="arial" size="3"></font><FONT style="BACKGROUND-COLOR: #ffffff" face="Arial">
  </FONT>
  <br>
  <form runat="server" ID="Form1">
   <TABLE id="Table1" cellSpacing="0" bgcolor="#6699cc" cellPadding="1" width="300" border="1">
    <TR>
     <TD><b>test</b>
     </TD>
    </TR>
     <TD>
      <asp:DataGrid id="DG1" runat="server" BorderColor="green" Width="640" PageSize="5" AllowPaging="true"
       OnPageIndexChanged="Page_Grid" BorderWidth="1" CellPadding="3" AutoGenerateColumns="false"
       ShowHeader="true" Visible="true" OnEditCommand="People_Edit" OnCancelCommand="People_Cancel"
       OnUpdateCommand="People_Update" OnDeleteCommand="People_Delete">
       <HeaderStyle BorderColor="White" BackColor="black" ForeColor="White" Font-Bold="True" Font-Name="Arial"
        Font-Size="9" HorizontalAlign="Center" />
       <ItemStyle BorderColor="" BackColor="#FFFFF0" ForeColor="Black" Font-Name="Arial" Font-Size="8"
        Font-Bold="False" HorizontalAlign="Center" />
       <EditItemStyle BorderColor="" BackColor="#FFFFF0" ForeColor="Black" Font-Name="Arial" Font-Size="7"
        Font-Bold="False" HorizontalAlign="Center" />
       <PagerStyle Mode="NumericPages" Font-Size="8" />
       <Columns>
        <asp:BoundColumn HeaderText="ID" ReadOnly="true" DataField="ID" />
        <asp:TemplateColumn>
         <HeaderTemplate>
          <b>代码</b>
         </HeaderTemplate>
         <ItemTemplate>
          <asp:Label Text='<%# DataBinder.Eval(Container.DataItem, "Code").ToString().Trim() %>' runat="server" ID="Label1" NAME="Label1"/>
         </ItemTemplate>
         <EditItemTemplate>
          <asp:TextBox id="Code" Text='<%# DataBinder.Eval(Container.DataItem, "Code").ToString().Trim() %>' runat="server" Width="100%"/>
         </EditItemTemplate>
        </asp:TemplateColumn>
        <asp:TemplateColumn>
         <HeaderTemplate>
          <b>名称</b>
         </HeaderTemplate>
         <ItemTemplate>
          <asp:Label Width="200" Text='<%# DataBinder.Eval(Container.DataItem, "Name").ToString().Trim() %>' runat="server" ID="Label2" NAME="Label2"/>
         </ItemTemplate>
         <EditItemTemplate>
          <asp:TextBox id="Name" Text='<%# DataBinder.Eval(Container.DataItem, "Name").ToString().Trim() %>' runat="server"/>
         </EditItemTemplate>
        </asp:TemplateColumn>
        <asp:EditCommandColumn ButtonType="PushButton" CancelText="取消" EditText="修改" UpdateText="更新" />
        <asp:ButtonColumn Text="删除" CommandName="Delete" ButtonType="PushButton"></asp:ButtonColumn>
       </Columns>
      </asp:DataGrid></TD>
    </TR>
   </TABLE>
  </form>
 </body>
</HTML>

Update.aspx.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace Client.Page.AreaInfo
{
 /// <summary>
 /// Update 的摘要说明。
 /// </summary>
 public class Update : System.Web.UI.Page
 {
  protected System.Web.UI.WebControls.DataGrid DG1;
  protected Classes.AreaInfo myClass=new Client.Classes.AreaInfo();
  private void Page_Load(object sender, System.EventArgs e)
  {
   if(!this.IsPostBack)
   {
    this.DG1.DataSource=myClass.bindGrid();
    this.DG1.DataBind();
   }
   // 在此处放置用户代码以初始化页面
  }
  public void Page_Grid(Object sender, DataGridPageChangedEventArgs e)
  {
   DG1.CurrentPageIndex = e.NewPageIndex;
   DG1.DataSource =myClass.bindGrid();
   DG1.DataBind();

  }
  public void DG1_Edit(Object sender, DataGridCommandEventArgs e)
  {
   DG1.EditItemIndex = e.Item.ItemIndex;
   DG1.DataSource =myClass.bindGrid();
   DG1.DataBind();

  }

  public void DG1_Cancel(Object sender, DataGridCommandEventArgs e)
  {   
   DG1.EditItemIndex = -1;
   DG1.DataSource = myClass.bindGrid();
   DG1.DataBind();

  }

  public void DG1_Update(Object sender, DataGridCommandEventArgs e)
  {
   string code = ((TextBox)e.Item.Cells[1].Controls[1]).Text;
   string name = ((TextBox)e.Item.Cells[2].Controls[1]).Text;
   int id=int.Parse(e.Item.Cells[0].Text);
   myClass.upDateArea(id,code,name);
   DG1.EditItemIndex = -1;
   DG1.DataSource = myClass.bindGrid();
   DG1.DataBind();
   

  }

  public void DG1_Delete(Object sender, DataGridCommandEventArgs e)
  {
   int id=int.Parse(e.Item.Cells[0].Text);
   myClass.deleteArea(id);
   this.DG1.DataSource=myClass.bindGrid();
   this.DG1.DataBind();

  }


  #region Web 窗体设计器生成的代码
  override protected void OnInit(EventArgs e)
  {
   //
   // CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
   //
   InitializeComponent();
   base.OnInit(e);
  }
  
  /// <summary>
  /// 设计器支持所需的方法 - 不要使用代码编辑器修改
  /// 此方法的内容。
  /// </summary>
  private void InitializeComponent()
  {   
   this.Load += new System.EventHandler(this.Page_Load);

  }
  #endregion
 }
}




CNBIE BLOG

DataGrid常见解决方案(三)--在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 asp?url=/library/en-us/dnbda/html/daab-rm.asp" target=_blank>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:

  1. If the main "select all" checkbox is checked, it will select all of the DataGrid checkboxes
  2. If the main "select all" checkbox is unchecked, then all of the DataGrid checkboxes get unselected
  3. 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



CNBIE BLOG

DataGrid传统分页方式

原文:DataGrid传统分页方式

此分页方式与传统ASP分页方式相仿.

DataGridPage.aspx

<%@ Page language="c#" Codebehind="DataGridPage.aspx.cs" AutoEventWireup="false" Inherits="netCRM.DataGridPage" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<HTML>
 <HEAD>
  <title>DataGridPage</title>
  <meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
  <meta name="CODE_LANGUAGE" Content="C#">
  <meta name="vs_defaultClients cript" content="Javas cript">
  <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
 </HEAD>
 <body MS_POSITIONING="GridLayout">
  <form id="Form1" method="post" runat="server">
   <asp:datagrid id="DataGrid1" runat="server" AlternatingItemStyle-BackColor="#eeeeee" HeaderStyle-BackColor="#aaaadd"
    Font-Size="8pt" Font-Name="Verdana" CellPadding="3" BorderWidth="1px" BorderColor="Black"
    PagerStyle-HorizontalAlign="Right" PagerStyle-Mode="NumericPages"
    PageSize="5" Font-Names="Verdana" Width="100%">
    <AlternatingItemStyle BackColor="#EEEEEE"></AlternatingItemStyle>
    <HeaderStyle BackColor="#AAAADD"></HeaderStyle>
    <PagerStyle HorizontalAlign="Right" Mode="NumericPages"></PagerStyle>
   </asp:datagrid>
  </form>
  <TABLE cellSpacing="0" cellPadding="1" width="100%" bgColor="#aaaadd" border="0">
   <TBODY>
    <TR>
     <TD>
      <TABLE cellSpacing="0" cellPadding="4" width="100%" bgColor="#fef8e2" border="0">
       <TBODY>
        <TR>
         <TD class="M" noWrap align="center"><asp:Literal id="Literal1" runat="server"></asp:Literal></TD>
        </TR>
        <TR>
         <TD class="C" noWrap align="center"><asp:Literal id="Literal2" runat="server"></asp:Literal></TD>
        </TR>
       </TBODY>
      </TABLE>
     </TD>
    </TR>
   </TBODY>
  </TABLE>
 </body>
</HTML>

DataGridPage.aspx.cs

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace netCRM
{
 /// <summary>
 /// DataGridPage 的摘要说明。
 /// </summary>
 public class DataGridPage : System.Web.UI.Page
 {
  protected System.Web.UI.WebControls.Literal Literal1;
  protected System.Web.UI.WebControls.Literal Literal2;
  protected System.Web.UI.WebControls.DataGrid DataGrid1;
 
  private void Page_Load(object sender, System.EventArgs e)
  {
   // 在此处放置用户代码以初始化页面
   if(!IsPostBack)
   {
    BindGrid();
   }
  }

  private void BindGrid()
  {
   string connstring = "Server=.;Database=NorthWind;User Id=sa;Password=;";
   string sql="Select * from Orders";
   SqlConnection conn = new  SqlConnection(connstring);
   conn.Open();
   DataSet ds = new DataSet();
   SqlDataAdapter sqlAdapter = new SqlDataAdapter(sql,conn);
   sqlAdapter.Fill(ds,"users");

   DataView dataview = new DataView();
   dataview = ds.Tables[0].DefaultView;

   DataGrid1.DataSource = ds.Tables[0].DefaultView;
   DataGrid1.DataBind();
   
   
   string cPage;
   int pageSize = 10;
   int currentPage;
   int pageCount;
   int numResults = 0;

   if (Request.QueryString["page"]==null)
   {
    cPage="1";
   }
   else
   {
    cPage=Request.QueryString["page"].ToString();
   }
   try
   {
    currentPage = Int32.Parse(cPage);
   }
   catch
   {
    currentPage = 1;
   }

   numResults = 0;
   int start = (int)((currentPage - 1) * pageSize);
   int to = (int)(currentPage * pageSize);
   if (start <= 0) start = 0;

   numResults = dataview.Count;
   int a1=0;
   pageCount = Math.DivRem(numResults,pageSize,out a1);
   if (a1>0)
   {
    pageCount++;
   }
   if(currentPage>pageCount || currentPage<=0)
   {
    currentPage = 1;
   }
   if(currentPage==pageCount)
   {
    to = dataview.Count;
   }
   
   // Create one DataTable with one column.
   DataTable myTable = new DataTable("myTable");
   myTable = dataview.Table.Clone();

   //DataColumn colItem1 = new DataColumn("name",Type.GetType("System.String"));
   //DataColumn colItem2 = new DataColumn("types",Type.GetType("System.String"));
   //DataColumn colItem3 = new DataColumn("vendor",Type.GetType("System.String"));
   //myTable.Columns.Add(colItem1);
   //myTable.Columns.Add(colItem2);
   //myTable.Columns.Add(colItem3);
   
   //add row
   DataRow NewRow;
   for(int i=start;i<numResults;i++)
   {
    if(i<to)
    {
     NewRow = myTable.NewRow();
     for(int k=0;k<dataview.Table.Columns.Count;k++)
     {
      NewRow[k] = dataview.Table.Rows[i][k];
     }
     myTable.Rows.Add(NewRow);
    }
   }
   myTable.AcceptChanges();

   DataView resultDataview = new DataView(myTable);
   DataGrid1.DataSource = resultDataview;
   DataGrid1.DataBind();

   /// <summary>
   ///  生成页导航条。
   /// </summary>
   string strNav = "";
   int endpage;
   if (currentPage>1)
   {
    strNav += "<a href='?page="+ (currentPage-1).ToString() +"'>上一页</a>  ";
   }
   if (currentPage>11)
   {
    strNav += "<a href='?page=1'>1</a> ...";
   }
   if(pageCount>currentPage+10)
   {
    endpage = currentPage+10;
   }
   else
   {
    endpage = pageCount;
   }
   for (int i=currentPage-10;i<endpage+1;i++)
   {
    if(i>=1)
    {
     if (i==currentPage)
     {
      strNav +="<font color=#990000><strong>"+ i.ToString() +"</strong></font> ";
     }
     else
     {
      strNav += "<a href='?page="+ i.ToString() +"'>"+ i.ToString() +"</a> ";
     }
    }
   }
   if((currentPage+10)<pageCount)
   {
    strNav += "... <a href='?page="+ pageCount.ToString() +"'>"+ pageCount.ToString() +"</a>";
   }
   if(currentPage<pageCount)
   {
    strNav += " <a href='?page="+ (currentPage+1).ToString() +"'>下一页</a>  ";
   }

   Literal1.Text = strNav;   
   Literal2.Text = "共 "+ numResults.ToString() +" 条供应信息,当前显示第 "+
    (start+1).ToString() +" - "+ to.ToString()  +" 条,共 "+ pageCount.ToString() +" 页";
  }

  #region Web 窗体设

CNBIE BLOG

DataGrid的客户端分页

原文:DataGrid的客户端分页

DataGrid的客户端分页


原著:Jeff Prosise

翻译:xiaojin


原文出处:aspx">MSDN Magazine Feb 2004 (aspx">Client-side Paging for DataGrids)

原代码下载:vckbase.com/code/downcode.asp?id=2256">WickedCode0402.exe (120KB)

  开发人员对ASP.NET中的DataGrid控件又爱又恨。一方面,DataGrids大大简化了在HTML中通过表格中描述数据源,另一方面,DataGrid在服务器端如此重要,导致了大量的页面请求被传回服务器。例如,当用户使用分页DataGrid时,从一个页面转到另一个页面就会导致页面请求传回服务器。这样就会降低系统的性能。毫无疑问,广大开发人员的心愿就是有一种好的DataGrid,能够使包括数据记录的页面时不必重复发送请求到服务器。
  从理论上讲,建立一个在客户端进行分页处理的HTML表格并不困难,因为有功能强大的客户端脚本。vckbase28/dotnet/csharp/wickedcode0401_fig.htm#fig1">Figure 1中的HTML页面演示了实现客户端分页的一种方法。当页面在浏览器中被查看时(见Figure 2),显示为一张表格。但是实际上有3张表格放在了<DIV>范围内。每一个<DIV>确保任一时刻只有一个表格是可见的。要显示前一页或后一页,可以通过少量的JavaScript语句隐藏当前的<DIV>模块来实现。表格的显示和不显示使之看起来就像是在一张表格。


Figure 2:分页的HTML表格

  我们可以用这个技术来实现DataGrid控件实现客户端分页。难点是如何修改DataGrid类来产生如vckbase28/dotnet/csharp/wickedcode0401_fig.htm#fig1">Figure 1那样的外观。
  这就是Wicked Code部分所要讨论的:通过建立一个插件取代客户端的分页,来增强DataGrid控件的性能。为了增加这个非常有用的工具,本文介绍一个通过继承并增加新功能来修改ASP.NET控件的好例子。

ClientPageDataGrid控件介绍
  ClientPageDataGrid是从DataGrid控件继承而来并增加了客户端分页支持的ASP.NET控件。由于它在功能上取代了DataGrid,因此你可以在任何能使用DataGrid控件的地方使用它。
  vckbase28/dotnet/csharp/wickedcode0401_fig.htm#fig3">Figure 3中的WEB页面是按以往的方法实现分页的:重复发送数据请求到服务器。该DataGrid被设置为允许分页(AllowPaging="true")和每页显示16条记录(PageSize="16")。点击该页中DataGrid下面任何一个按钮,页面请求都将被发送到服务器并且触发PageIndexChanged事件,同时激发OnNewPage方法。OnNewPage方法将设置DataGrid的CurrentPageIndex属性为上一页或下一页的索引,并将新页面返回给客户端。
  vckbase28/dotnet/csharp/wickedcode0401_fig.htm#fig4">Figure 4显示了用ClientPageDataGrid实现的页面,页面变化如红色所示。DataGrid控件被ClientPageDataGrid控件取代了。为了实现分页,AllowPaging="true"改成了AllowClientPaging="true",PageSize="16" 改成了ClientPageSize="16"。OnPageIndexChanged属性和OnNewPage方法在新控件中已经被删除了。现在就可以实现完全在客户端分页了。
  要使用ClientPageDataGrid 这个控件,请先将ClientPaging.aspx拷贝到ASP.NET WEB服务器的一个虚目录中(例如:wwwroot),接着拷贝动态库ClientPageDataGrid.dll到该虚目录的bin子目录,最后在浏览器中打开ClientPaging.aspx这个文件。你就可以看到如Figure 5中所示的页面,可以用左下角的箭头向前或向后翻页。ClientPaging.aspx看起来并且感觉就像是ServerPaging.aspx,但实际上是大不相同的。ServerPaging.aspx页面多次从服务器端装入,并且翻页的速度受限于服务器和客户端的连接情况。相反,ClientPaging.aspx装入速度稍微慢点,是因为要下载页面全部记录,这比一页的数据要多。但是一旦页面装入完毕,翻页速度就与连接速度无关了。


Figure 5 ClientPageDataGrid

  ClientPageDataGrid的开发接口包括4个公共属性和其他从DataGrid继承来的属性(如vckbase28/dotnet/csharp/wickedcode0401_fig.htm#fig6">Figure 6所示)。AllowClientPaging属性设置是否允许翻页,默认为允许。因此你可以在设置ClientPageDataGrid时略过AllowClientPaging=true。ClientPageSize属性设置每页显示的记录条数,ClientPageCount获得页面的总数。ClientCurrentPageIndex设置当先哪页被显示。下面的Page_Load方法设置名字为MyDataGrid的ClientPageDataGrid控件显示第2页(索引0表示第1),而不是第1页。

void Page_Load (Object sender, EventArgs e) {     if (!IsPostBack) {         BindDataGrid ();         MyDataGrid.ClientCurrentPageIndex = 1;     } } 
  当ClientPageDataGrid所在页面的请求发送到服务器后,页面返回后,ClientCurrentPageIndex属性就被更新,来指示显示哪一页。服务器并不知道用户在看哪一页。

ClientPageDataGrid详情
  ClientPageDataGrid输出标页数的HTML表格从使用Render方法开始,如vckbase28/dotnet/csharp/wickedcode0401_fig.htm#fig7">Figure 7所示。你可以通过本文上面的链接下载完整的源代码。Render是一个从System.Web.UI.Control继承来的一个虚方法。在Microsoft? .NET Framework中,当包括该控件的页面被请求时,Render方法被用来将控件加入到HTML中去。
  ClientPageDataGrid重写了DataGrid的方法并且多次调用基类的实现,而不是一次。特别说明的是,ClientPageDataGrid在输出每一页时调用DataGrid.Render,同时通过对RenderBeginTag和RenderEndTag的调用将输出加入到<DIV>模块中。在调用基类的Render方法前,ClientPageDataGrid.Render调用一个本地的ShowItems方法来隐藏那些在页面上不显示的记录,方法是设置那些行的Visible属性为否(见vckbase28/dotnet/csharp/wickedcode0401_fig.htm#fig8">Figure 8)。
  当ClientPageDataGrid被设置为每页显示16条记录,也就意味着第1个<DIV>包括该表格的前16条记录,第2个<DIV>包括该表格紧接着的16条记录,以此类推。除1个之外所有的<DIV>模块通过设置样式 style=”display:none”来隐藏。只有显示页的索引等于ClientCurrentPageIndex时,<DIV>模块才被显示,它的样式被设置为style=”display:block”。
  ClientPageDataGrid中的每一页包括一个分页器,该分页器存在于DataGrid当中,因为ClientPageDataGrid重写了DataGrid的DataBind方法,并且通过设置AllowPaging为真、PageSize设置为每页显示条数来调用。ClientPageDataGrid.cs中大部分代码就是来使页面正常工作,确保支持Previous/next-style分页器(<PagerStyle Mode="NextPrev">)和数字分页器(<PagerStyle Mode="NumericPages">)。
  传统的包括LinkButtons的DataGrid分页器,发送页面请求到服务器,然后产生PageIndexChanged事件。ClientPageDataGrid用指向客户端的JavaScript函数的链接取代了这些LinkButtons。UpdatePager方法(如vckbase28/dotnet/csharp/wickedcode0401_fig.htm#fig9">Figure 9所示),在Render调用基类的Render方法之前被取代。UpdatePager通过在DataGrid中搜索类型为ListItemType.Pager的行,来找到要显示的页面,接着就删除页面中的控件,加入需要的控件。
下面是一个传统的DataGrid,触发分页器时输出HTML的例子:
<tr>   <td colspan="3">     <a href= "javascript:__doPostBack(''MyDataGrid$_ctl20$_ctl0'','''')">       <</a>      <a href="javascript:__doPostBack(''MyDataGrid$_ctl20$_ctl1'','''')">       ></a>   </td> </tr> 
下面是由ClientPageDataGrid控件实现的同一个页面:
<tr>   <td colspan="3">     <a href="javascript:__onPrevPage (''MyDataGrid'');"><</a>      <a href="javascript:__onNextPage (''MyDataGrid'');">></a>   </td> </tr> 
  当ClientPageDataGrid.OnPreRender调用Page.RegisterClientScriptBlock时,导航标记所指向的JavaScript函数就被打上标记。调用RegisterClientScriptBlock确保包括这些函数的脚本块仅仅被输出一次,甚至当页面包括ClientPageDataGrid的多个实例时也是这样。
  虽然ClientPageDataGrid并没有包括任何自己的服务器请求,但是页面的其他控件仍然会导致向服务器的请求。这产生了两个问题。第一,当请求发生时,ClientCurrentPageIndex应当进行更新,因此服务器端代码能决定哪一页被显示。第二,当页面从服务器反馈回后,ClientPageDataGrid应当能被当前页保存。用另外的话说就是,当第3页显示时向服务器请求时,ClientPageDataGrid的代码应当加入一个样式style="display: block"给包括第3页的<DIV>模块,而其他<DIV>模块没有。
为解决这些问题,ClientPageDataGrid注册了一个隐含字段controlid__ PAGENUM:
Page.RegisterHiddenField (ClientID + "__PAGENUM",     ClientCurrentPageIndex.ToString ()); 
  当页面更新时,在客户端中通过输出页面进行分页的JavaScript函数来更新隐含的字段。当页面请求发给服务器后,隐含字段的值被加入到服务器返回数据中。ClientPageDataGrid的LoadViewState方法从返回的数据中读取这个值,并且通过RestoreCurrentPageIndex方法设置ClientCurrentPageIndex的值,代码如下:
string page = Page.Request[ClientID + "__PAGENUM"];   ... ClientCurrentPageIndex = Convert.ToInt32 (page); 
  请求时间处理代码能通过ClientCurrentPageIndex属性的值判断用户要读取哪一页。同时因为ClientPageDataGrid.Render使用ClientCurrentPageIndex来判断哪一个<DIV>被显示,因此当前显示页直到页面数据请求发生后才隐藏。
  在LoadViewState带来的反馈数据中包括当前页索引非常有用。首先,当前页的索引不会被设置直到控件被组装,存在LoadViewState中。此外,由于LoadViewState在主页的装入事件触发前被调用,Page_Load方法能通过ClientCurrentPageIndex属性值来判断用户的当前页的索引。那样是非常重要的,因为当前页的索引会带来其他的变化。
  RestoreCurrentPageIndex同样被ClientPageDataGrid的DataBind方法调用,而且仅仅是,如果不是被LoadViewState调用的话。为什么呢?因为如果视图状态被禁用了(即EnableViewState=false),则LoadViewState就不能被ASP.NET运行库调用。如果视图状态被禁用,页面就会调用DataBind重新装载控件,因此调用DataBind方法就是根据返回数据恢复当前页的索引就很自然了。
  或许你注意到了ClientPageDataGrid的DataBind方法调用绑定数据并不是一次,而是两次(见vckbase28/dotnet/csharp/wickedcode0401_fig.htm#fig10">Figure 10)。第1次调用是基类的DataBind方法给ClientPageDataGrid提供记录条数,产生一个包括所有数据的DataGrid。DataGrid放在ClientPageDataGrid下面,为描述数据源提供服务。
  ClientPageDataGrid的DataBing方法另一个特别的地方是它将DataReaders转变为DataSets.。有两个理由这么做。首先,DataReader只能被绑定一次,因为它是只能向前读取的数据源。其次,通常的DataGrid并不支持DataReaders作为数据源,如果AllowPaging值为true的话,直到AllowCustomPaging也为true时才行。在程序内部巧妙地将DataReaders转换为DataSets就解决了这些问题,并且确保ClientPageDataGrid工作起来像使用DataReaders一样,而实际上是在使用DataSets。

警告
  难道在客户端分页就没有缺点吗?你讲对了。数据量越大,页面装入速度就会越慢,因为要装入全部的数据,而不只是显示页的数据。相对较小的记录集,1000条记录或更少,你就可以不关注这个问题了。对于非常大的记录集,装入时间就将会是难以接受的长。
  另外一个要考虑的因素是带宽,大的DataGrid会在两方面增加下载时间。第一会增大HTML表格,第二会增加视图状态的大小。因为ASP.NET通过一个隐含字段保持视图状态,DataGrid的内容本来就是在HTTP请求时显示一次,在HTTP响应时显示两次。这就是要保证数据量少,大的数据量还是最好用服务器端分页。当有大量的记录时你还要使用ClientPageDataGrid,最好设置控件的EnableViewState属性为false,并且在每一个页面请求时绑定数据。这样会减少相应大小约2/3。
  对ClientPageDataGrid的最后一个思考是,你大概会设置ClientPageSize为一个偶数,如果你使用AlternatingItemStyle来呈现奇数项来区别于偶数项。第一页将在顶端拥有一个不交互的项。第二页将有一个交互的项,并且其他也这样。这样会导致用户考虑为什么表格格式变来变去,每次都不同于前面的页面。

结束语
  DataGrid是ASP.NET中最重要的功能之一,归功于它在重用类中隐含了复杂的构造和非凡的逻辑。ClientPageDataGrid 将给服务器端的控件带来一个适应未来步伐的思想,证明了不仅仅要考虑如何修改嵌入控件来使用,而且还要考虑如何扩展客户端的功能。服务器控件依赖于客户端脚本,工作将更有效率,这是一个非常好的主意。希望所有控件的作者同意这个看法。
有什么问题或建议,请发邮件到:wicked@microsoft.com
 
作者简介
  Jeff Prosise是MSDN杂志的资深编辑,和一些书的作者,例如《Programming Microsoft .NET》(微软出版社,2002),同时他还是Wintellect网站(http://www.wintellect.com)的共同创办人,该网站是一个专门提供Microsoft .NET的咨询和教育公司。 
 
本文出自 aspx">MSDN Magazine,aspx">2004年2月号。你可以从附近的报摊获得,更好的方法是 aspx">订阅。

本文由 VCKBASE MTT 翻译


CNBIE BLOG

datagrid分页《非控件版》

原文:datagrid分页《非控件版》

首先对我之前的发表的那篇补充一下:当你在你的建立的工程中要用到我做的那个用户控件的话:声明 Protected DataGridPage1 As DataGridPage,前是你拖进来的控件名,后是你定义用户控件。然后在你代码中要用你的控件就写上:

DataGridPage1.SetTarget(MyDataGrid, New BindDataDelegate(AddressOf binddata))
DataGridPage1.SetStyle(10, False)

下划线部分是你自己写的一个绑定之类的涵数。SUB,FUNCTION 等。

以下是我不做成控件时的代码:

HTML:

<%@ Page Language="vb" AutoEventWireup="false" Codebehind="fenye.aspx.vb" Inherits="datagridtitle.fenye"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
 <HEAD>
  <title>fenye</title>
  <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
  <meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
  <meta name="vs_defaultClients cript" content="Javas cript">
  <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
 </HEAD>
 <body MS_POSITIONING="GridLayout">
  <form id="Form1" method="post" runat="server">
   <FONT face="MS UI Gothic">
    <asp:DataGrid id="MyDataGrid" style="Z-INDEX: 101; LEFT: 0px; POSITION: absolute; TOP: 112px"
     runat="server" Width="744px" Height="224px" AllowPaging="True">
     <PagerStyle Visible="False"></PagerStyle>
    </asp:DataGrid>
    <asp:LinkButton id="LinkButton1" style="Z-INDEX: 102; LEFT: 8px; POSITION: absolute; TOP: 96px"
     runat="server" Width="48px" Height="8px">第一頁</asp:LinkButton>
    <asp:LinkButton id="LinkButton2" style="Z-INDEX: 103; LEFT: 64px; POSITION: absolute; TOP: 96px"
     runat="server" Width="56px">前一頁</asp:LinkButton>
    <asp:LinkButton id="LinkButton3" style="Z-INDEX: 104; LEFT: 120px; POSITION: absolute; TOP: 96px"
     runat="server" Width="48px">後一頁</asp:LinkButton>
    <asp:LinkButton id="LinkButton4" style="Z-INDEX: 105; LEFT: 176px; POSITION: absolute; TOP: 96px"
     runat="server" Width="80px">最後一頁</asp:LinkButton>
    <asp:Label id="Label1" style="Z-INDEX: 106; LEFT: 552px; POSITION: absolute; TOP: 80px" runat="server"
     Width="56px">跳轉到:</asp:Label>
    <asp:TextBox id="txtGoPage" style="Z-INDEX: 107; LEFT: 624px; POSITION: absolute; TOP: 80px"
     runat="server" Width="48px" Height="24px"></asp:TextBox>
    <asp:Button id="btnGo" style="Z-INDEX: 108; LEFT: 680px; POSITION: absolute; TOP: 80px" runat="server"
     Height="24px" Width="56px" Text="Button"></asp:Button>
    <asp:Label id="lblCurrentIndex" style="Z-INDEX: 109; LEFT: 296px; POSITION: absolute; TOP: 88px"
     runat="server" Height="24px" Width="120px">Label</asp:Label>
    <asp:Label id="lblPageCount" style="Z-INDEX: 110; LEFT: 424px; POSITION: absolute; TOP: 88px"
     runat="server" Width="112px">Label</asp:Label></FONT>
  </form>
 </body>
</HTML>

WEB代码:

 Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        ' ページを初期化するユーザー コードをここに挿入します。
        If Not IsPostBack Then

            ViewState("strSort") = "orderid"

            MyDataGrid.DataSource = GetDv(ViewState("strSort").ToString())

            MyDataGrid.DataBind()
            ShowStatsPage()
            'Call orderbind()
        End If
    End Sub
    Private Function GetDv(ByVal strSort As String) As DataView

 

        Dim dv As DataView

        Dim CN As New SqlConnection

        Try

 

            CN.ConnectionString = "data source=yangchangquan;initial catalog=Northwind;persist security info=False;user id=sa;Password=pass;"

            CN.Open()

 

            Dim adp As SqlDataAdapter = New SqlDataAdapter("select * from orders", CN)

            Dim ds As New DataSet

            adp.Fill(ds)


           
            dv = ds.Tables(0).DefaultView

        Catch ex As Exception

#If DEBUG Then

            Session("Error") = ex.ToString()

            Response.Redirect("../error.aspx")

#End If

        Finally

            '???接

            CN.Close()

        End Try

        '排序

        dv.Sort = strSort

        Return dv

    End Function

 


    Private Sub MyDataGrid_SortCommand(ByVal source As System.Object, ByVal e As System.Web.UI.WebControls.DataGridSortCommandEventArgs)
        MyDataGrid.CurrentPageIndex = 0

        '得到排序的列

        ViewState("strSort") = e.SortExpression.ToString()

        MyDataGrid.DataSource = GetDv(ViewState("strSort").ToString())

        MyDataGrid.DataBind()

        ShowStatsPage()
    End Sub

 


    Private Sub btnGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGo.Click
        Dim pageI As Integer
        If (txtGoPage.Text <> "") Then
            pageI = CInt(Trim(txtGoPage.Text)) - 1
            If (pageI >= 0 And pageI < (MyDataGrid.PageCount)) Then
                MyDataGrid.CurrentPageIndex = pageI
            End If
        End If
        ViewState("strSort") = "orderid"

        MyDataGrid.DataSource = GetDv(ViewState("strSort").ToString())

        MyDataGrid.DataBind()
        ShowStatsPage()
    End Sub

Private Sub ShowStatsPage()
        lblCurrentIndex.Text = "[<font color='blue'>當前頁為:" & (MyDataGrid.CurrentPageIndex + 1) & "頁</font>]"
        lblPageCount.Text = "[<font color='blue'>共:" & MyDataGrid.PageCount & "頁</font>]"

    End Sub

 Private Sub LinkButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LinkButton1.Click
        MyDataGrid.CurrentPageIndex = 0
        ViewState("strSort") = "orderid"

        MyDataGrid.DataSource = GetDv(ViewState("strSort").ToString())

        MyDataGrid.DataBind()
        ShowStatsPage()
    End Sub

    Private Sub LinkButton4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LinkButton4.Click
        MyDataGrid.CurrentPageIndex = (MyDataGrid.PageCount - 1)
        ViewState("strSort") = "orderid"

        MyDataGrid.DataSource = GetDv(ViewState("strSort").ToString())

        MyDataGrid.DataBind()
        ShowStatsPage()
    End Sub

    Private Sub LinkButton2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LinkButton2.Click
        If (MyDataGrid.CurrentPageIndex > 0) Then
            MyDataGrid.CurrentPageIndex = MyDataGrid.CurrentPageIndex - 1
            ViewState("strSort") = "orderid"

            MyDataGrid.DataSource = GetDv(ViewState("strSort").ToString())

            MyDataGrid.DataBind()
            ShowStatsPage()
        End If
    End Sub

    Private Sub LinkButton3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LinkButton3.Click
        If (MyDataGrid.CurrentPageIndex < (MyDataGrid.PageCount - 1)) Then
            MyDataGrid.CurrentPageIndex = MyDataGrid.CurrentPageIndex + 1
            ViewState("strSort") = "orderid"

            MyDataGrid.DataSource = GetDv(ViewState("strSort").ToString())

            MyDataGrid.DataBind()
            ShowStatsPage()
        End If
    End Sub

完成;





CNBIE BLOG

datagrid技巧之一:代码控制选中行的颜色

原文:datagrid技巧之一:代码控制选中行的颜色

大家都知道datagrid是一个使用频率很高的控件,在编写ASP.NET代码的时候,我们总希望能让用户选中指定的行以后,让那一行用不同的颜色显示,虽然datagrid样式也有这个功能,但是我们如何编写代码实现呢?

在本例子中,我们首先动态产生1000行,然后当用户选中datagrid中的某一行的时候,那一行就会变为蓝色。代码如下:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace WebApplication_rd
{
 /// <summary>
 /// Demostrates how to have a datagrid server control be bookmarked
 /// </summary>
 public class datagrid : System.Web.UI.Page
 {

  protected System.Web.UI.WebControls.DataGrid DGProducts;
  int bookmarkIndex = 0; // The index of the row that should be scrolled to
  int itemCount = 0; // Counter for the amount of items on the page
  bool bookMark = true; // Controls whether or not the page is bookmarked
 
  #region DGProducts EventHandlers

  private void DGProducts_ItemDataBound(object source, DataGridItemEventArgs e) {
  
   if (bookMark) {
   
    LiteralControl anchor = new LiteralControl();
    anchor.Text = "<a name=\"" + itemCount.ToString() + "\">";
    itemCount ++;
    e.Item.Cells[0].Controls.Add(anchor);
    
   }
   
  }

  private void DGProducts_ItemCommand(object source, DataGridCommandEventArgs e) {
   
   if (e.CommandName == "Select") {
  
    e.Item.BackColor = Color.Blue;

    if (bookMark) {
     bookmarkIndex = e.Item.ItemIndex;
     this.Inserts criptBlock();
    }   
   }
  
  }

  
  #endregion

  #region EventHandlers
  private void Page_Load(object sender, System.EventArgs e)
  {

   this.Bind();

  }

  #endregion

  #region User Defined

  private void Inserts criptBlock() {
  
   System.Text.StringBuilder js cript = new System.Text.StringBuilder();
   js cript.Append("<s cript language=\"Javas cript\">");
   js cript.Append("location.href=\"#");
   js cript.Append(this.bookmarkIndex.ToString());
   js cript.Append("\";");
   js cript.Append("</s cript>");

   this.RegisterClients criptBlock("Bookmark", js cript.ToString());
 
  }

  
  private void Bind()
  {
  
   DGProducts.DataSource = this.CreateDataSource(1000);
   DGProducts.DataBind();  
  
  }


  private DataTable CreateDataSource(int count) {
  
   DataTable table = new DataTable();
   DataColumn column = null;
   DataRow row = null;

   // Create 5 columns
   for (int iCol = 0; iCol < 5; iCol++) {
    
    column = new DataColumn("Column: " + iCol.ToString(), typeof(string));
    table.Columns.Add(column);

   }

   //Create Rows based on count variable
   for (int iRows = 0; iRows < count; iRows ++) {
   
    row = table.NewRow();
       
    for (int iCol = 0; iCol < 5; iCol ++) {
     
     row[iCol] = "Value: " + iCol.ToString();
    
    
    }

    table.Rows.Add(row);
   
   }
   
   return table;
  
  }


  #endregion

  #region Web Form Designer generated code
  override protected void OnInit(EventArgs e)
  {
   InitializeComponent();
   base.OnInit(e);
  }
  
  private void InitializeComponent()
  {   
   this.DGProducts.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.DGProducts_ItemCommand);
   this.DGProducts.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.DGProducts_ItemDataBound);
   this.Load += new System.EventHandler(this.Page_Load);

  }
  #endregion
 }

}



posted on 2007-03-16 13:40  yiriqing  阅读(511)  评论(0)    收藏  举报