.Net源码论坛 [ 繁体中文 ]

发新话题 回复该主题

项目总结(四) datagrid自定义分页(存储过程)篇 [复制链接]

楼主
datagrid自定义分页是datagrid的一个重要的功能,datagrid自定义分页主要用于数据源较大时。因为数据源大(记录多),加载时间长,反应慢,耗服务器的资源。而且每显示一页就要重新加载所有的数据。而如果我们用自定义分页,则每一次只加载一页的记录,也就是只加载我们要显示的记录。这样加载数据时间短,反应快,节约服务器的资源。在做项目的过程中,我们也经常需要用到自定义功能。今天我们就说说怎样自定义分页。
先看看datagrid的自定义分页的原理,它主要依据两个主要属性,第一个就是VirtualItemCount属性,它表示datagrid一共要显示多少条记录,它就是的作用是用于生成pager(分页导航行),通过结合另外两个属性pagesize和PageButtonCount,datagrid就知道要分成多少页了及当前要显示多少个分页按钮,我们不难得到总共要显示的总页数=(VirtualItemCount+pagesize-1)/pagesize;如要总页数 <PageButtonCount,则显示总页数个按钮;如果总页数> PageButtonCount,则显示PageButtonCount个按钮,当然到了最后一页就只显示VirtualItemCount%   pagesize(总记录条数除以每页显示记录的余数)个按钮。另一个重要的属性就是datasource(数据源),自定义分页的一个重要的特点是显示数据源中所有的记录,如果数据源中有一条记录,则显示一条记录;如果数据源中有一万条记录,则它会显示一万条记录,可能你的机子就慢了   :   )。所以自定义最重要的一点是如何设置或获取数据源了。
接下来,我们先说说自定义分页的主要步骤:
1. 设置datagrid的VirtualItemCount属性;
2. 获取datagrid的datasource(数据源);
3. 绑定数据到datagrid;
4. 设置新页的页码(datagrid.currentpageindex属性)。
重复上述2,3,4步。
下面我们以一个例子来讲解datagrid   的自定义过程。
例子要求机子装有ms   sql   server   7.0   或   2000,当然还要能运行asp.net页了(废话)。
我们先来写一个通用的存储过程,用于分页,返回某页的要显示的记录集,及一个输出参数--总的记录条数,但这个存储过程有缺陷,例如只能用于单表查询,必须要有条件语句等。
CREATE   PROCEDURE   up_custompage   @vc_order_column_name   varchar(100),@vc_select_column_list   varchar(100),
@vc_select_table_list   varchar(100),@vc_condition   varchar(100),@page_size   int,@current_page   int,@total1   int   output  
/*
(
@vc_order_column_name   :表要排序列的列名,只能按一列排序,而且该列必须得在输出列表中;
@vc_select_column_list   :返回列的列名列表;
@vc_select_table_list:要查询的表名;
@vc_condition:查询条件的字符串,必须要有查询条列,否则会抛出异常;
@page_size:每页显示记录的条数;
@current_page:当前页的页码;
@total1:所有符合条件的记录的总数。
构造的sql语句=select   top   每页显示记录的条数   *   from   (select   top   每页显示记录的条数   返回列的列名列表   from   要查询的表名   where   要排序列的列名   in   (select   top   每页显示记录的条数   X   当前页的页码     要排序列的列名     from   要查询的表名   where   查询条件   order   by   要排序列的列名)   order   by   要排序列的列名   desc   )   as   temp1   order   by   要排序列的列名
)
*/
AS
--声明要用到的变量,@temp1是正常的分页语句字符串,@temp2是最后一页的分页语句字符串,@page_total表一共有几页,@last_page
--是最后一页的页码
declare   @temp1   varchar(500),@temp2   nvarchar(500),@page_total   int,@last_page   int
--构造获得总页的数的检索语句
set   @temp2=N 'select   @total2=count(*)   from   '   +   @vc_select_table_list   +   '   where   '   +   @vc_condition
--执行检索语句,取得总的记录条数
exec   sp_executesql   @temp2,N '   @total2   int   output   ',@total1   output

/*构造分页检索语句,基本原理是先取出@page_size*@current_page条记录,相当于是取出当前页及当前页前面的所有页面的记录然后取出当前面所要显示的记录,也就是反序排序后取前@page_size条记录;最后再反序排序(因为前面的顺序被反排过一次,现在再反排一次,正好是我们要的顺序),最后执行,返回结果集。
*/
if   @total1> 0
begin
set   @page_total=(@total1+@page_size-1)/@page_size
--如果当前页不是最后一页
if   @current_page <@page_total
set   @temp1= 'select   top   '   +   cast(@page_size   as   varchar(4))   +   '   *   from  
(select   top   '   +   cast(@page_size   as   varchar(4))     +   '   '   +   @vc_select_column_list   +   '   from   '   +   @vc_select_table_list   + '   where   '   +   @vc_order_column_name  
+   '   in   (select   top   '   +   cast(@page_size*@current_page   as   varchar(10))   +   '   '   +   @vc_order_column_name   +   '   from   '   +  
@vc_select_table_list   +   '   where   '+   @vc_condition     +   '   order   by   '   +
@vc_order_column_name   +   ')   order   by   '   +   @vc_order_column_name     +   '   DESC)   as   temp1   order   by   '   +   @vc_order_column_name  
else
--最后一页只返回分页后的最后几条记录,也就是@total1%@page_size条记录
begin
set   @last_page=@total1%@page_size
set   @temp1= 'select   top   '   +   cast(@last_page   as   varchar(4))   +   '   *   from  
(select   top   '   +   cast(@last_page   as   varchar(4))     +   '   '   +   @vc_select_column_list   +   '   from   '   +   @vc_select_table_list   + '   where   '   +   @vc_order_column_name  
+   '   in   (select   top   '   +   cast(@total1   as   varchar(10))   +   '   '   +   @vc_order_column_name   +   '   from   '   +  
@vc_select_table_list   +   '   where   '+   @vc_condition     +   '   order   by   '   +
@vc_order_column_name   +   ')   order   by   '   +   @vc_order_column_name     +   '   DESC)   as   temp1   order   by   '   +   @vc_order_column_name  
end
--执行检索
exec(@temp1)
end
else
return

-------------------------------------------------------------------------

然后在新建一个aspx页面,代码如下:
<%@   Page   language= "c# "   Codebehind= "custompage.aspx.cs "   AutoEventWireup= "false "   Inherits= "cyc_test.custompage "   %>
<!DOCTYPE   HTML   PUBLIC   "-//W3C//DTD   HTML   4.0   Transitional//EN "   >
<HTML>
<HEAD>
<title> custompage </title>
<meta   content= "Microsoft   Visual   Studio   7.0 "   name= "GENERATOR ">
<meta   content= "C# "   name= "CODE_LANGUAGE ">
<meta   content= "JavaScript "   name= "vs_defaultClientScript ">
<meta   content= "http://schemas.microsoft.com/intellisense/ie5 "   name= "vs_targetSchema ">
<style> A   {   BEHAVIOR:   url(MouseOver.htc)   }
HR   {   COLOR:   black;   HEIGHT:   2px   }
.StdText   {   FONT-WEIGHT:   bold;   FONT-SIZE:   9pt;   FONT-FAMILY:   verdana   }
.StdTextBox   {   BORDER-RIGHT:   black   1px   solid;   BORDER-TOP:   black   1px   solid;   FONT-SIZE:   9pt;   FILTER:   progidXImageTransform.Microsoft.dropshadow(OffX=2,   OffY=2,   Color= 'gray ',   Positive= 'true ');   BORDER-LEFT:   black   1px   solid;   BORDER-BOTTOM:   black   1px   solid;   FONT-FAMILY:   verdana   }
.Shadow   {   FILTER:   progidXImageTransform.Microsoft.dropshadow(OffX=2,   OffY=2,   Color= 'gray ',   Positive= 'true ')   }
</style>
</HEAD>
<body   style= "FONT-FAMILY:   arial "   bgColor= "ivory "   MS_POSITIONING= "GridLayout ">
<form   id= "custompage "   method= "post "   runat= "server ">
<h2> 项目总结之datagrid自定义分页篇
</h2>
<asp:label   id= "Label1 "   runat= "server "   font-bold= "true "   cssclass= "StdText "> 当前路径:   </asp:label> <asp:label   id= "lblURL "   style= "COLOR:   blue "   runat= "server "   cssclass= "StdText "> </asp:label>
<!--   Query   --> <br>
<asp:label   id= "Label2 "   runat= "server "   cssclass= "stdtext "   Text= "查询语句: "> </asp:label>
<asp:textbox   id= "Textbox1 "   runat= "server "   cssclass= "stdtextbox "   text= "SELECT   employeeid,   firstname,   lastname,title   FROM   Employees   where   employeeid> 0   order   by   employeeid "   width= "765px "   Enabled= "false "> </asp:textbox>
<hr>
<!--   Show   the   information   -->
<aspatagrid   id= "grid "   runat= "server "   OnPageIndexChanged= "PageIndexChanged "   AllowCustomPaging= "True "   AllowPaging= "True "   PageSize= "5 "   BorderWidth= "1 "   BorderColor= "black "   BorderStyle= "solid "   BackColor= "White "   CssClass= "Shadow "   GridLines= "vertical "   CellSpacing= "0 "   CellPadding= "2 "   Font-Names= "Verdana "   Font-Size= "Smaller ">
<PagerStyle   Font-Bold= "true "   Mode= "NumericPages "   BackColor= "palegreen "   />
<AlternatingItemStyle   BackColor= "#eeeeee "   />
<ItemStyle   BackColor= "White "   />
<HeaderStyle   Font-Bold= "True "   ForeColor= "White "   BackColor= "Navy "   />
</aspatagrid> </form>
</body>
</HTML>
再写后台的源代码:
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;
using   System.Data.SqlClient;

namespace   cyc_test
{
///   <summary>
///   custompage   的摘要说明。
///   </summary>
public   class   custompage   :   System.Web.UI.Page
{
protected   System.Web.UI.WebControls.Label   Label1;
protected   System.Web.UI.WebControls.Label   lblURL;
protected   System.Web.UI.WebControls.Label   Label2;
protected   System.Web.UI.WebControls.TextBox   Textbox1;
protected   System.Web.UI.WebControls.DataGrid   grid;

private   void   Page_Load(object   sender,   System.EventArgs   e)
{
//   第一次加载页时,初始化
if   (!Page.IsPostBack)
{
lblURL.Text   =   Request.Url   +   " <hr> ";
createdatasource(1);
}
}

//绑定datagrid的函数
protected   void   createdatasource(int   current_page)
{
string   str_table_name,str_column_list,str_order_column,str_condition;
//查询的表名
str_table_name= "employees ";
//返回的列名列表
str_column_list= "employeeid,firstname,lastname,title ";
//排序列的列名
str_order_column= "employeeid ";
//查询的表件
str_condition= "employeeid> 0 ";
string   strConn   =   "DATABASE=Northwind;SERVER=localhost;UID=sa;PWD=; ";
SqlConnection   conn   =   new   SqlConnection(strConn);
//声明执行存储过程的SqlCommand  
SqlCommand   scd_sel=new   SqlCommand( "up_custompage ",conn);
scd_sel.CommandType=CommandType.StoredProcedure;
//给存储过程的参数赋值
SqlParameter   sp_temp;
sp_temp=scd_sel.Parameters.Add( "@vc_order_column_name ",SqlDbType.VarChar,100);
sp_temp.Direction=ParameterDirection.Input;
sp_temp.Value=str_order_column;
sp_temp=scd_sel.Parameters.Add( "@vc_select_column_list ",SqlDbType.VarChar,100);
sp_temp.Direction=ParameterDirection.Input;
sp_temp.Value=str_column_list;
sp_temp=scd_sel.Parameters.Add( "@vc_select_table_list ",SqlDbType.VarChar,100);
sp_temp.Direction=ParameterDirection.Input;
sp_temp.Value=str_table_name;
sp_temp=scd_sel.Parameters.Add( "@vc_condition ",SqlDbType.VarChar,100);
sp_temp.Direction=ParameterDirection.Input;
sp_temp.Value=str_condition;
sp_temp=scd_sel.Parameters.Add( "@page_size ",SqlDbType.Int);
sp_temp.Direction=ParameterDirection.Input;
sp_temp.Value=grid.PageSize;
sp_temp=scd_sel.Parameters.Add( "@current_page ",SqlDbType.Int);
sp_temp.Direction=ParameterDirection.Input;
sp_temp.Value=current_page;
sp_temp=scd_sel.Parameters.Add( "@total1 ",SqlDbType.Int);
sp_temp.Direction=ParameterDirection.Output;

//执行存储过程
SqlDataAdapter   sda=new   SqlDataAdapter();
sda.SelectCommand=scd_sel;
if   (conn.State==ConnectionState.Closed)
conn.Open();
DataSet   ds=new   DataSet();
sda.Fill(ds, "tb1 ");
conn.Close();
//设置VirtualItemCount属性
grid.VirtualItemCount=(int)scd_sel.Parameters[ "@total1 "].Value;
//绑定数据源
grid.DataSource=ds.Tables[ "tb1 "].DefaultView;
grid.DataBind();
}

#region   Web   Form   Designer   generated   code
override   protected   void   OnInit(EventArgs   e)
{
//
//   CODEGEN:该调用是   ASP.NET   Web   窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}

///   <summary>
///   设计器支持所需的方法   -   不要使用代码编辑器修改
///   此方法的内容。
///   </summary>
private   void   InitializeComponent()
{        
this.grid.ItemCreated   +=   new   System.Web.UI.WebControls.DataGridItemEventHandler(this.grid_ItemCreated);
this.grid.PageIndexChanged   +=   new   System.Web.UI.WebControls.DataGridPageChangedEventHandler(this.PageIndexChanged);
this.Load   +=   new   System.EventHandler(this.Page_Load);

}
#endregion
//datagrid的ItemCreated事件,用于定制分页导航行
private   void   grid_ItemCreated(object   sender,   System.Web.UI.WebControls.DataGridItemEventArgs   e)
{

ListItemType   elemType   =   e.Item.ItemType;
//定制分页导航行,样式为[1]   [2]   第   3   页   [4]
if   (elemType   ==   ListItemType.Pager)  
{

TableCell   pager   =   (TableCell)   e.Item.Controls[0];

for   (int   i=0;   i <pager.Controls.Count;   i+=2)  
{
Object   o   =   pager.Controls;
if   (o   is   LinkButton)  
{
LinkButton   h   =   (LinkButton)   o;
h.Text   =   "[   "   +   h.Text   +   "   ] ";  
}
else
{
Label   l   =   (Label)   o;
l.Text   =   "第 "   +   l.Text   +   “页”;  
}
}
}
}
//页选中(分页)事件
public   void   PageIndexChanged(object   source,   System.Web.UI.WebControls.DataGridPageChangedEventArgs   e)
{
grid.CurrentPageIndex   =   e.NewPageIndex;
//页码值是从零开始的,所以要加一
createdatasource(grid.CurrentPageIndex+1);
}
}
}

      要运行上面的示例,请按上面的顺序先创建存储过程,再写页面的代码,最后是源代码。示例参考了《构建Web解决方案---应用ASP.NET和ADO.NET》中的分页思路。在本机调试通过。大家只要明白存储过程分页的思想就可以了。如果大家有更好的方案,请提出来,也许你的更好!
      这一段时间又开始了新的项目,所以这篇文章写得比较仓促,可能有些地方讲得不明白,大家可以提问和讨论。希望对大家有所帮助。
分享 转发
TOP
沙发

这个我没看懂,直接调试可用吗
TOP
板凳

呵呵呵 凑字数吗啊
TOP
地板

嗯哪   九江市 就是啊 啊呵呵呵这次hide
TOP
五楼

好东西 顶起来啊 呵呵 支持啊 基恩才
TOP
六楼

挺好   不错
到可道非常道
TOP
七楼

存储过程太复杂
TOP
八楼

好东西,参考一下!
TOP
九楼

很好! 赚分中!
TOP
十楼

值得收藏
TOP
发新话题 回复该主题