** Henry ** ** 手记 —Web Form ** ** 中的 Datagrid ** ** 的自定义分页 **
韩睿 ( 05/31/2003)
ASP.NET 带给我们很多惊喜,强大的 Web Form 控件自然是其中的重要部分。这其中,最受关注的当然是 Datagrid 。在 ASP中用 HTML 标记语法来输出数据的方法在 Datagrid 数据绑定面前显得如此繁杂。但是只使用 Datagrid 自身的功能,还是达不到实际的工作要求。本文就是给大家演示如何提高我们的工作效率、降低服务器的负载压力。
- ** Datagrid ** ** 的分页显示 **
当查询到的数据很多,在一屏内显示出来篇幅太长的时候,我们可以利用 Datagrid 的分页功能让用户通过上下页的切换来查看数据。设置方法很简单:在 datagrid 的属性处点击“属性生成器”,然后在“分页”栏进行如图 1 所示的设置,页大小的行数即决定了每页显示出几行数据记录。
图 1 分页设置
- ** 自定义导航栏 **
在图 1 的属性页中的“格式”栏中,我们可以设置“页导航”的外观样式。但是很多程序设计人员都喜欢用自己定义的导航栏,而不使用默认的上下页按钮或数字按钮(即出现 1 、 2 、 3 ……页号的形式)。那么我们可以这样来做:
(1) 如果要保留默认的导航栏,请不用看这一小节。如果要隐藏起默认的页导航栏。就请将 PageStyle 的 visible 属性设置为 false 。或在图 1 “页导航”中,不勾选“显示导航按钮”即可。
(2) 在写自定义导航栏时,主要是利用 CurrentPageIndex 属性来设置页:
" 第一页 ":
DataGrid1.CurrentPageIndex = 0;
" 上一页 ":
if (DataGrid1.CurrentPageIndex > 0)
DataGrid1.CurrentPageIndex -= 1;
" 下一页 ":
if (DataGrid1.CurrentPageIndex < (DataGrid1.PageCount - 1))
DataGrid1.CurrentPageIndex += 1;
" 最后一页 ":
DataGrid1.CurrentPageIndex = (DataGrid1.PageCount - 1);
(3) 需要注意的是: Web Form 是一种无状态的编程方式,我们在自定义了导航栏按钮的代码后,需要再次加载 Datagrid 的数据源。否则将看不到页切换的效果。也就是说,我们需要在按钮的 click 事件中加入重新加载数据源的代码,比如我们可以将加载的代码写在如下方法 SetGridSource 中,在按钮 Click 的代码最后加入 SetGridSource()这句调用代码。
private void SetGridSource()
{
SqlConnection MyConnection = new SqlConnection(YourOwnConnectionString);
string SelectCommand = "SELECT * FROM YOURTABLE";
SqlDataAdapter MyCommand = new SqlDataAdapter(SelectCommand, MyConnection);
DataSet ds = new DataSet();
MyCommand.Fill(ds, " YOURTABLE ");
DataView dv = ds.Tables["YOURTABLE "].DefaultView;
DataGrid1.DataSource = dv;
DataGrid1.DataBind();
}
或者我们可以在 Page_load 中写入 SetGridSource里的代码,使浏览器在页切换重置时可以重新加载并绑定Datagrid的数据源。要注意的是,上述代码不能写在首次加载判断 if (!IsPostBack) 语句中
(4) 在页面上我们一般需要显示总页数与当前页面这样的信息。 与WinForm中的Datagrid不同的是 ,在WinForm中需要获取与数据相关的信息,只能从Datagrid的数据源,比如DataTable中去获得数据行数,某单元格的值等信息。被WinForm中的dataset与datagrid之间的关系弄得头晕的朋友就不用再害怕了,在WebForm中,我们只要从Datagrid中就可以直接获得这些信息了。总页数是Datagrid的PageCount属性;当前页数是CurrentPageIndex属性值+1来表示,这是由于CurrentPageIndex是从0开始计数的。
- ** 自定义分页 **
采用 Datagrid 属性生成器中的分页方式,我们都会感觉到方便的欣喜。但是,用上面所说的方法,每次页切换时,都会用 SELECT * FROM YOURTABLE 这样的 SQl 语句去提取出全部的数据,而没有任何与页有关的筛选器。这大大降低了我们 Web 程序的效率,也增加了服务器的负担。 Datagrid 提供的分页特点也变得名不副实。我们希望分页能真正的实现减少每次下载的数据量的功能,就要写代码控制住每次提取的数据量大小。
要使用自定义分页,就要将 AllowCustomPaging 属性设置为 true 。然后基于 PageSize 和 VirtualItemCount 属性的值计算要显示 DataGrid 控件中每一项所需的页数。
PageSize 表示的是在 DataGrid 控件的单页上显示的项数,默认值为 10 。
VirtualItemCount 表示的是总数目。那么页数自然是 VirtualItemCount/PageSize
(1) 当然是首先要知道一共有多少条数据,然后我们才好进行分配,写在 Page_load里:
if (! IsPostBack )
{
StartIndex = 0; //StartIndex是int类型的公用变量
SqlConnection MyConnection = new SqlConnection(YourOwnConnectionString);
SqlCommand MyCommand = new SqlCommand("SELECT mycount = COUNT(*) FROM Table",MyConnection);
MyConnection.Open();
SqlDataReader dr = MyCommand.ExecuteReader(CommandBehavior.SingleRow);
if (dr.Read())
DataGrid1.VirtualItemCount = ( int )dr["mycount"];
dr.Close();
MyConnection.Close();
SetGridSource(StartIndex, "上一页"); //看看现在的形参有什么不同哦
}
注: 这里说一个本文研究范围之外的知识点,就是上面 dr的赋值代码中,我们用的是 MyCommand.ExecuteReader(CommandBehavior.SingleRow) ,而大家一般用的只是 MyCommand.ExecuteReader() ,但请记住,如果返回记录集只有一行的话,用 ** CommandBehavior.SingleRow ** 进行标识可以提高应用程序的执行效率。这是因为不注明的一般情况下, MyCommand 执行是 使用 ** IRowset ** 接口。而注明了之后,就会利用 ** IRow ** 接口(如果可用)执行绑定。其中的差别请关注笔者的后续作品。
(2) 现在的主要变化当然在重新绑定数据源的方法 SetGridSource中。我们给该方法加入两个输入参数:当前的页面、发出控制(即判断用户点击的是“上一页”还是“下一页”等按钮)。下面的代码主要实现按钮型导航栏,有两个按钮“上一页”与“下一页”。“第一页”与“最后一页”的写法,请网友们自行实现。在如下示例中,column1为数据表之主键。每页有5行数据。
private void SetGridSource (int StartPosition, string GoToPage)
{
SqlConnection MyConnection = new SqlConnection(YourOwnConnectionString);
SqlCommand MyCommand = null;
switch (GoToPage)
{
case "上一页":
MyCommand = new
SqlCommand("SELECT TOP 5 * FROM Table WHERE column1 >= @ID ORDER BY column1",MyConnection);
if (StartPosition == 0)
MyCommand.Parameters.Add("@ID",SqlDbType.NVarChar, 10).Value = ""; //这里参数10是ID字段的长度
else
MyCommand.Parameters.Add("@ID",SqlDbType.NVarChar,10).Value =
ViewState[(DataGrid1.CurrentPageIndex + 1).ToString()];
break;
case "下一页":
MyCommand = new
SqlCommand("SELECT TOP 5 * FROM Table WHERE column1 > @ID ORDER BY column1",MyConnection); //注意:这里用的是>,不是>=哟
MyCommand.Parameters.Add("@ID", SqlDbType.NVarChar,10).Value = DataGrid1.Items[4].Cells[0].Text; //Items[4]表示第5行即每页显示的最后一行
break;
}
MyConnection.Open();
SqlDataReader dr = MyCommand.ExecuteReader();
DataGrid1.DataSource = dr;
DataGrid1.DataBind();
dr.Close();
MyConnection.Close();
//用ViewState来缓存刚才访问过的那一页的第一行中的主键值
ViewState[(DataGrid1.CurrentPageIndex + 1).ToString()]=DataGrid1.Items[0].Cells[0].Text;
}
注:如果是 oracle数据库,可以在 where 条件中用 rownum 来控制上下页的条数与内容。
请在按扭的 click事件里的最后调用 SetGridSource 方法,参数
StartPosition= DataGrid1.CurrentPageIndex *DataGrid1.PageSize;
[参考]关于Datagrid分页的更详细的内容,可以参看华中科技大学出版社出版的章立民先生所著之《用实例学ASP.NET--使用VB.NET与ADO.NET》一书
----
声明:本文版权与解释权归韩睿所有,如需转载,请保留完整的内容及此声明。
QQ: 18349592
E-Mail: [email protected]
请访问本人专栏: http://www.csdn.net/develop/author/netauthor/Latitude/