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代码如下:
<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>

控件代码:
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, falsetrue);
            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("&nbsp;"));
            cell_1.Controls.Add(lbtnPrev);
            cell_1.Controls.Add(
new LiteralControl("&nbsp;"));
            cell_1.Controls.Add(lbtnNext);
            cell_1.Controls.Add(
new LiteralControl("&nbsp;"));
            cell_1.Controls.Add(lbtnLast);
            cell_1.Controls.Add(
new LiteralControl("&nbsp;"));

            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


posted @ 2007-08-21 02:01 jecray 阅读(1124) 评论(4) 编辑 收藏