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:所有符合条件的记录的总数。
)
*/
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: progid:DXImageTransform.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: progid:DXImageTransform.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 -->
<asp:datagrid 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" />
</asp:datagrid></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[i];
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》中的分页思路。在本机调试通过。大家只要明白存储过程分页的思想就可以了。如果大家有更好的方案,请提出来,也许你的更好!
这一段时间又开始了新的项目,所以这篇文章写得比较仓促,可能有些地方讲得不明白,大家可以提问和讨论。希望对大家有所帮助。
语句的整体架构
select top 每页显示的记录条数 * from
(
select top 每页显示的记录条数 要显示的字段列表 from 要查询的表的列表(包括连接语句)where 排序字段 in
(
select top 每页显示的记录条数 排序字段 from 要查询的表的列表(包括连接语句)where order by 排序字段
)
order by 排序字段 desc
)
as temp1
order by 排序字段
<script language="javascript" type="text/javascript"> ad_width=468; ad_height=60; adcss=2; unionuser=19; ad_type='j'; count=5; </script><script language="javascript" src="http://tagegg.csdn.net/showads.js" type="text/javascript"></script><script language="JavaScript1.1" src="http://tagegg.csdn.net/a.aspx?action=displayad&unionuser=19&unionurl=http%3A%2F%2Fblog.csdn.net%2Ffest%2Farchive%2F2006%2F06%2F29%2F850938.aspx&adcss=2&ad_type=j&width=468&height=60&ad_color=&ad_color_border=&count=5" type="text/javascript"></script><script language="javascript" src="/js/showgm.js" type="text/javascript"></script><script src="http://www.csdn.net/common/counter.js" type="text/javascript"></script><script type="text/javascript">
</script><script type="text/javascript">
</script>