asp.net自定义控件之 利用ObjectDataSource和Repeater创建URL分页控件
在项目中有时候需要进行URL分页.使用URL分页可以方便的进行URL重写,适用于纯粹的显示信息列表,可以尽量减少如ViewStates这些附加信息,使页面代码变得清晰.
在这篇利用anthem和ObjectDataSource创建无刷新的自定义分页控件 文章中 已经实现ObjectDataSource和GridView的结合.
具有的优点:
1.是数据源采用ObjectDataSource,可以实现将页面UI和业务逻辑分开。分页时,只读取当前页面需要的数据,提高了分页速度。
2.继承Anthem中的GridView控件,可以实现无刷新翻页功能,增强了用户体验。
3.只需给控件指定DataSourceID,实现DataSourceID中的分页方法,简单易用。
这次采用Repeater和ObjectDataSource相结合同样具备了上述优点. 只是将无刷新分页改变成URL分页的形式.
效果如图:

ObjectDataSource的业务逻辑代码和上一篇的一模一样 ,不需要做任何修改.
可以参照利用anthem和ObjectDataSource创建无刷新的自定义分页控件 中ObjectDataSource的配置.
aspx代码如下:
控件代码:
上面仅仅是实现了基本的功能.
需要注意的是性能方面的 , ObjectDataSource本身就是通过反射机制来执行指定类的相应方法,因此性能方面是不理想的. 易用性的提高一般都会带来性能上的损失.需要好好权衡.
Repeater具有DataSourceID属性, 但只能执行默认的select检索 ,因此需要通过反射动态的执行SelectCountMethod , 无疑又是一个性能上的损失.可以将第一次查询得到的记录总数添加到Cache中去, 以URL信息作为key,以后翻页时 ,就不用执行了SelectCountMethod了.不知道还有什么好的解决方案.Created by jecray
在这篇利用anthem和ObjectDataSource创建无刷新的自定义分页控件 文章中 已经实现ObjectDataSource和GridView的结合.
具有的优点:
1.是数据源采用ObjectDataSource,可以实现将页面UI和业务逻辑分开。分页时,只读取当前页面需要的数据,提高了分页速度。
2.继承Anthem中的GridView控件,可以实现无刷新翻页功能,增强了用户体验。
3.只需给控件指定DataSourceID,实现DataSourceID中的分页方法,简单易用。
这次采用Repeater和ObjectDataSource相结合同样具备了上述优点. 只是将无刷新分页改变成URL分页的形式.
效果如图:

ObjectDataSource的业务逻辑代码和上一篇的一模一样 ,不需要做任何修改.
可以参照利用anthem和ObjectDataSource创建无刷新的自定义分页控件 中ObjectDataSource的配置.
aspx代码如下:
<div style="width:450px">
<cc1:JARepeater ID="JARepeater1" runat="server" DataSourceID="ObjectDataSource1" PageSize="10">
<HeaderTemplate>
<table class="thinTable">
<tr>
<td >
产品编号</td>
<td>
产品名称</td>
<td>
价格</td>
<td>
单位数量</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr >
<td>
<%# Eval("ProductID")%>
</td>
<td>
<%# Eval("ProductName")%>
</td>
<td>
<%# Eval("UnitPrice")%>
</td>
<td>
<%# Eval("QuantityPerUnit")%>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table></FooterTemplate>
</cc1:JARepeater>
<asp:ObjectDataSource ID="ObjectDataSource1" EnablePaging="true" TypeName="Test.Controls.App_Data.DataAccess"
SelectCountMethod="GetPageCount" SelectMethod="GetCustomList" StartRowIndexParameterName="startRowIndex"
MaximumRowsParameterName="maximumRows" runat="server"></asp:ObjectDataSource>
</div>
<cc1:JARepeater ID="JARepeater1" runat="server" DataSourceID="ObjectDataSource1" PageSize="10">
<HeaderTemplate>
<table class="thinTable">
<tr>
<td >
产品编号</td>
<td>
产品名称</td>
<td>
价格</td>
<td>
单位数量</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr >
<td>
<%# Eval("ProductID")%>
</td>
<td>
<%# Eval("ProductName")%>
</td>
<td>
<%# Eval("UnitPrice")%>
</td>
<td>
<%# Eval("QuantityPerUnit")%>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table></FooterTemplate>
</cc1:JARepeater>
<asp:ObjectDataSource ID="ObjectDataSource1" EnablePaging="true" TypeName="Test.Controls.App_Data.DataAccess"
SelectCountMethod="GetPageCount" SelectMethod="GetCustomList" StartRowIndexParameterName="startRowIndex"
MaximumRowsParameterName="maximumRows" runat="server"></asp:ObjectDataSource>
</div>
控件代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Web.UI.HtmlControls;
using System.Reflection;
namespace Jec.CustomControls
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:JARepeater runat=server></{0}:JARepeater>")]
public class JARepeater : Repeater, INamingContainer
{
//翻页按钮
private HyperLink lbtnFirst;
private HyperLink lbtnPrev;
private HyperLink lbtnNext;
private HyperLink lbtnLast;
//当前页数 总页数 每页记录数 总记录数
private Label lbPageIndex;
private Label lbPageCount;
private Label lbPageSize;
private Label lbRecordCount;
//页码变量
private int recordCount;
private int pageIndex;
private int pageSize = 5;
private string urlPara = "pageID";
[Bindable(true), DefaultValue(10)]
public int PageSize
{
get { return pageSize; }
set { pageSize = value; }
}
[Browsable(false)]
public int PageIndex
{
get { return pageIndex; }
set { pageIndex = value; }
}
[Browsable(false)]
public int RecordCount
{
get { return recordCount; }
set { recordCount = value; }
}
[Browsable(false)]
public int PageCount
{
get
{
if (RecordCount % PageSize == 0)
{
return RecordCount / PageSize;
}
else
{
return RecordCount / PageSize + 1;
}
}
}
//页面地址 构造url用
[Browsable(false)]
public string RawURL
{
get { return Page.Request.Path; }
}
//传递页码参数的名称
[Bindable(true), DefaultValue(typeof(String),"pageID")]
public string URLPara
{
get { return urlPara; }
set { urlPara = value; }
}
protected override void CreateChildControls()
{
//初始化 导航按钮
lbtnFirst = new HyperLink();
lbtnFirst.ID = "lbtnFirst";
lbtnFirst.Text = "首页";
lbtnPrev = new HyperLink();
lbtnPrev.ID = "lbtnPrev";
lbtnPrev.Text = "上一页";
lbtnNext = new HyperLink();
lbtnNext.ID = "lbtnNext";
lbtnNext.Text = "下一页";
lbtnLast = new HyperLink();
lbtnLast.ID = "lbtnLast";
lbtnLast.Text = "尾页";
//初始化 状态列表
lbPageIndex = new Label();
lbPageIndex.ID = "lbPageIndex";
lbPageCount = new Label();
lbPageCount.ID = "lbPageCount";
lbPageSize = new Label();
lbPageSize.ID = "lbPageSize";
lbRecordCount = new Label();
lbRecordCount.ID = "lbRecordCount";
int.TryParse(HttpContext.Current.Request.QueryString[URLPara], out pageIndex);
if (PageIndex != 0)
PageIndex--;
this.SelectArguments.StartRowIndex = PageIndex * PageSize;
this.SelectArguments.MaximumRows = PageSize;
base.CreateChildControls();
}
protected override void Render(HtmlTextWriter writer)
{
string typeName = ((ObjectDataSource)this.Parent.FindControl(this.DataSourceID)).TypeName;
string countMethodName = ((ObjectDataSource)this.Parent.FindControl(this.DataSourceID)).SelectCountMethod;
Type type = System.Web.Compilation.BuildManager.GetType(typeName, false, true);
MethodInfo methodInfo = type.GetMethod(countMethodName);
object instance = Activator.CreateInstance(type);
object[] parameters = null;
int.TryParse(methodInfo.Invoke(instance, parameters).ToString(), out recordCount);
RecordCount = recordCount;
SetPagerStatus();
Table tbl = new Table();
tbl.BorderWidth = 0;
tbl.Width = Unit.Percentage(100);
tbl.Rows.Add(new TableRow());
TableCell cell_1 = new TableCell();
cell_1.Controls.Add(lbtnFirst);
cell_1.Controls.Add(new LiteralControl(" "));
cell_1.Controls.Add(lbtnPrev);
cell_1.Controls.Add(new LiteralControl(" "));
cell_1.Controls.Add(lbtnNext);
cell_1.Controls.Add(new LiteralControl(" "));
cell_1.Controls.Add(lbtnLast);
cell_1.Controls.Add(new LiteralControl(" "));
TableCell cell_2 = new TableCell();
//cell_2.Controls.Add(ddl);
cell_2.Controls.Add(new LiteralControl(" 当前页数:"));
cell_2.Controls.Add(lbPageIndex);
cell_2.Controls.Add(new LiteralControl(" 总页数:"));
cell_2.Controls.Add(lbPageCount);
cell_2.Controls.Add(new LiteralControl(" 每页记录数:"));
cell_2.Controls.Add(lbPageSize);
cell_2.Controls.Add(new LiteralControl(" 总记录数:"));
cell_2.Controls.Add(lbRecordCount);
tbl.Rows[0].Cells.Add(cell_1);
tbl.Rows[0].Cells.Add(cell_2);
tbl.Rows[0].Cells[0].HorizontalAlign = HorizontalAlign.Left;
tbl.Rows[0].Cells[1].HorizontalAlign = HorizontalAlign.Right;
//输出repeater
base.Render(writer);
//输出分页信息
tbl.RenderControl(writer);
}
//设置分页状态
public void SetPagerStatus()
{
//如果没记录则不显示
if (PageCount == 0)
{
this.Visible = false;
return;
}
//第一页
if (PageIndex == 0)
{
lbtnFirst.Enabled = false;
lbtnPrev.Enabled = false;
lbtnNext.Enabled = true;
lbtnNext.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageIndex + 2);
lbtnLast.Enabled = true;
lbtnLast.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageCount);
}
//最后一页
else if (PageIndex == PageCount - 1)
{
lbtnFirst.Enabled = true;
lbtnFirst.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", 1);
lbtnPrev.Enabled = true;
lbtnPrev.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageIndex);
lbtnNext.Enabled = false;
lbtnLast.Enabled = false;
}
//中间页Created by jecray
else
{
lbtnFirst.Enabled = true;
lbtnFirst.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", 1);
lbtnPrev.Enabled = true;
lbtnPrev.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageIndex);
lbtnNext.Enabled = true;
lbtnNext.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageIndex + 2);
lbtnLast.Enabled = true;
lbtnLast.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageCount);
}
lbPageCount.Text = PageCount.ToString();
lbRecordCount.Text = RecordCount.ToString();
lbPageIndex.Text = (PageIndex + 1).ToString();
lbPageSize.Text = PageSize.ToString();
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Web.UI.HtmlControls;
using System.Reflection;
namespace Jec.CustomControls
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:JARepeater runat=server></{0}:JARepeater>")]
public class JARepeater : Repeater, INamingContainer
{
//翻页按钮
private HyperLink lbtnFirst;
private HyperLink lbtnPrev;
private HyperLink lbtnNext;
private HyperLink lbtnLast;
//当前页数 总页数 每页记录数 总记录数
private Label lbPageIndex;
private Label lbPageCount;
private Label lbPageSize;
private Label lbRecordCount;
//页码变量
private int recordCount;
private int pageIndex;
private int pageSize = 5;
private string urlPara = "pageID";
[Bindable(true), DefaultValue(10)]
public int PageSize
{
get { return pageSize; }
set { pageSize = value; }
}
[Browsable(false)]
public int PageIndex
{
get { return pageIndex; }
set { pageIndex = value; }
}
[Browsable(false)]
public int RecordCount
{
get { return recordCount; }
set { recordCount = value; }
}
[Browsable(false)]
public int PageCount
{
get
{
if (RecordCount % PageSize == 0)
{
return RecordCount / PageSize;
}
else
{
return RecordCount / PageSize + 1;
}
}
}
//页面地址 构造url用
[Browsable(false)]
public string RawURL
{
get { return Page.Request.Path; }
}
//传递页码参数的名称
[Bindable(true), DefaultValue(typeof(String),"pageID")]
public string URLPara
{
get { return urlPara; }
set { urlPara = value; }
}
protected override void CreateChildControls()
{
//初始化 导航按钮
lbtnFirst = new HyperLink();
lbtnFirst.ID = "lbtnFirst";
lbtnFirst.Text = "首页";
lbtnPrev = new HyperLink();
lbtnPrev.ID = "lbtnPrev";
lbtnPrev.Text = "上一页";
lbtnNext = new HyperLink();
lbtnNext.ID = "lbtnNext";
lbtnNext.Text = "下一页";
lbtnLast = new HyperLink();
lbtnLast.ID = "lbtnLast";
lbtnLast.Text = "尾页";
//初始化 状态列表
lbPageIndex = new Label();
lbPageIndex.ID = "lbPageIndex";
lbPageCount = new Label();
lbPageCount.ID = "lbPageCount";
lbPageSize = new Label();
lbPageSize.ID = "lbPageSize";
lbRecordCount = new Label();
lbRecordCount.ID = "lbRecordCount";
int.TryParse(HttpContext.Current.Request.QueryString[URLPara], out pageIndex);
if (PageIndex != 0)
PageIndex--;
this.SelectArguments.StartRowIndex = PageIndex * PageSize;
this.SelectArguments.MaximumRows = PageSize;
base.CreateChildControls();
}
protected override void Render(HtmlTextWriter writer)
{
string typeName = ((ObjectDataSource)this.Parent.FindControl(this.DataSourceID)).TypeName;
string countMethodName = ((ObjectDataSource)this.Parent.FindControl(this.DataSourceID)).SelectCountMethod;
Type type = System.Web.Compilation.BuildManager.GetType(typeName, false, true);
MethodInfo methodInfo = type.GetMethod(countMethodName);
object instance = Activator.CreateInstance(type);
object[] parameters = null;
int.TryParse(methodInfo.Invoke(instance, parameters).ToString(), out recordCount);
RecordCount = recordCount;
SetPagerStatus();
Table tbl = new Table();
tbl.BorderWidth = 0;
tbl.Width = Unit.Percentage(100);
tbl.Rows.Add(new TableRow());
TableCell cell_1 = new TableCell();
cell_1.Controls.Add(lbtnFirst);
cell_1.Controls.Add(new LiteralControl(" "));
cell_1.Controls.Add(lbtnPrev);
cell_1.Controls.Add(new LiteralControl(" "));
cell_1.Controls.Add(lbtnNext);
cell_1.Controls.Add(new LiteralControl(" "));
cell_1.Controls.Add(lbtnLast);
cell_1.Controls.Add(new LiteralControl(" "));
TableCell cell_2 = new TableCell();
//cell_2.Controls.Add(ddl);
cell_2.Controls.Add(new LiteralControl(" 当前页数:"));
cell_2.Controls.Add(lbPageIndex);
cell_2.Controls.Add(new LiteralControl(" 总页数:"));
cell_2.Controls.Add(lbPageCount);
cell_2.Controls.Add(new LiteralControl(" 每页记录数:"));
cell_2.Controls.Add(lbPageSize);
cell_2.Controls.Add(new LiteralControl(" 总记录数:"));
cell_2.Controls.Add(lbRecordCount);
tbl.Rows[0].Cells.Add(cell_1);
tbl.Rows[0].Cells.Add(cell_2);
tbl.Rows[0].Cells[0].HorizontalAlign = HorizontalAlign.Left;
tbl.Rows[0].Cells[1].HorizontalAlign = HorizontalAlign.Right;
//输出repeater
base.Render(writer);
//输出分页信息
tbl.RenderControl(writer);
}
//设置分页状态
public void SetPagerStatus()
{
//如果没记录则不显示
if (PageCount == 0)
{
this.Visible = false;
return;
}
//第一页
if (PageIndex == 0)
{
lbtnFirst.Enabled = false;
lbtnPrev.Enabled = false;
lbtnNext.Enabled = true;
lbtnNext.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageIndex + 2);
lbtnLast.Enabled = true;
lbtnLast.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageCount);
}
//最后一页
else if (PageIndex == PageCount - 1)
{
lbtnFirst.Enabled = true;
lbtnFirst.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", 1);
lbtnPrev.Enabled = true;
lbtnPrev.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageIndex);
lbtnNext.Enabled = false;
lbtnLast.Enabled = false;
}
//中间页Created by jecray
else
{
lbtnFirst.Enabled = true;
lbtnFirst.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", 1);
lbtnPrev.Enabled = true;
lbtnPrev.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageIndex);
lbtnNext.Enabled = true;
lbtnNext.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageIndex + 2);
lbtnLast.Enabled = true;
lbtnLast.NavigateUrl = String.Concat(RawURL, "?", URLPara, "=", PageCount);
}
lbPageCount.Text = PageCount.ToString();
lbRecordCount.Text = RecordCount.ToString();
lbPageIndex.Text = (PageIndex + 1).ToString();
lbPageSize.Text = PageSize.ToString();
}
}
}
上面仅仅是实现了基本的功能.
需要注意的是性能方面的 , ObjectDataSource本身就是通过反射机制来执行指定类的相应方法,因此性能方面是不理想的. 易用性的提高一般都会带来性能上的损失.需要好好权衡.
Repeater具有DataSourceID属性, 但只能执行默认的select检索 ,因此需要通过反射动态的执行SelectCountMethod , 无疑又是一个性能上的损失.可以将第一次查询得到的记录总数添加到Cache中去, 以URL信息作为key,以后翻页时 ,就不用执行了SelectCountMethod了.不知道还有什么好的解决方案.Created by jecray
