Reload

Remember

导航

带分页功能的Repeater控件

Posted on 2004-07-19 09:16  Handi.Z  阅读(2546)  评论(15编辑  收藏  举报
模仿MS PetShop重写了Repeater控件,使其具有分页功能。
.cs
using System;
using System.Data;
using System.Collections;
using System.Text.RegularExpressions;
using System.Web.UI.WebControls;


namespace Common.WebControls
{
    
public class MyRepeater : Repeater
    
{
        
//常量
        protected const string HTML1 = "<table cellpadding=0 cellspacing=0><tr><td align={0} class=pageHeader>";
        
protected const string HTML2 = "</td></tr><tr class=gridNav><td>";
        
protected const string HTML3 = "</td></tr><tr><td align={0} class=pageFooter>";
        
protected const string HTML4 = "</td></tr></table>";

        
private const string LINK = "<a href=?{0}={1} class=pageLink>{2}</a>";
        
private const string LINK_NEXT = "<a href=?{0}={1} title='下{2}页' class=pageLink>{3}</a>";
        
private const string LINK_PREV = "<a href=?{0}={1} title='上{2}页' class=pageLink>{3}</a>";

        
//私有变量
        private string mstrEmptyText = "";//DataSource为空的时候显示的字
        private string mstrPageKey = "Page";//在地址栏上显示的页码关键字,比如page=1
        private string mstrPageIndexAlign = "right";//页码对齐方式
        private string mstrPrevPageText = "<<";//上页文字
        private string mstrNextPageText = ">>";//下页文字
        private PagerPosition pagePosition = PagerPosition.TopAndBottom;//页码位置,上、下、上下都有
        private PagerMode pageMode = PagerMode.NumericPages;//页导航元素模式
        private int intPageIndexCount = 10;//显示的页码数
        private int intPageSize = 10;//一页显示的记录数
        private int intCurrentPage = 1;//当前页
        private IList dataSource;//数据源,必须可以转换为IList
        private bool blnRealSource = false;//数据源已分页

        
private int intItemCount;

        
/// <summary>
        
/// 数据源为空时显示的文本,默认为空
        
/// </summary>

        public string EmptyText
        
{
            
set { mstrEmptyText = value; }
        }


        
public bool RealSource
        
{
            
get return blnRealSource; }
            
set { blnRealSource = value; }
        }


        
/// <summary>
        
/// 获取或设置自定义地址栏上页码标志关键字,默认为Page。
        
/// 如果页面有两个MyRepeater,必须定义两个不同的PageKey。
        
/// 否则不能正确定位第二个MyRepeater。
        
/// </summary>

        public string PageKey
        
{
            
get return mstrPageKey; }
            
set { mstrPageKey = value; }
        }


        
/// <summary>
        
/// 获取或设置要在 MyRepeater 控件的单页上显示的项数。
        
/// 默认为10项。
        
/// </summary>

        public int PageSize
        
{
            
get return intPageSize; }
            
set { intPageSize = value; }
        }


        
/// <summary>
        
/// 获取或设置当前显示页的索引。默认为1。
        
/// </summary>

        public int CurrentPageIndex
        
{
            
get return intCurrentPage; }
            
set {intCurrentPage = value; }
        }


        
/// <summary>
        
/// 获取或设置 MyRepeater 控件中页导航元素的位置。
        
/// 默认为 TopAndBottom。
        
/// </summary>

        public PagerPosition PagePosition
        
{
            
get return pagePosition; }
            
set { pagePosition = value; }
        }


        
/// <summary>
        
/// 获取或设置一个值,该值指定页导航元素是显示链接到下一页和前一页的按钮,还是显示直接与某一页链接的数值按钮。
        
/// 默认为 NumericPages。
        
/// </summary>

        public PagerMode PageMode
        
{
            
get return pageMode; }
            
set { pageMode = value; }
        }


        
/// <summary>
        
/// 获取 MyRepeater 控件中页导航元素的对齐方式。
        
/// 默认为right。
        
/// </summary>

        public HorizontalAlign PageAlign
        
{
            
set { mstrPageIndexAlign = value.ToString(); }
        }


        
/// <summary>
        
/// 获取或设置为前一页按钮显示的文本。
        
/// </summary>

        public string PrevPageText
        
{
            
get return mstrPrevPageText; }
            
set { mstrPrevPageText = value; }
        }


        
/// <summary>
        
/// 获取或设置为下一页按钮显示的文本。
        
/// </summary>

        public string NextPageText
        
{
            
get return mstrNextPageText; }
            
set { mstrNextPageText = value; }
        }


        
/// <summary>
        
/// 获取显示 MyRepeater 控件中各项所需的总页数。
        
/// </summary>

        public int PageCount
        
{
            
get return (intItemCount - 1/ intPageSize + 1; }
        }


        
/// <summary>
        
/// 设置 MyRepeater 控件中页导航元素显示的页码数。
        
/// 默认为10。
        
/// </summary>

        public int PageIndexCount
        
{
            
set { intPageIndexCount = value; }
        }


        
/// <summary>
        
/// 设置 MyRepeater 控件的数据源。
        
/// 可以接受 DataSet、DataTable和所以实现了IList借口的数据源。
        
/// </summary>

        public override object DataSource
        
{
            
set
            
{
                
try
                
{
                    
if(value == null)
                    
{
                        dataSource 
= null;
                        intItemCount 
= 0;
                    }

                    
else if(value.GetType() == typeof(DataTable))//数据源是DataTable,转化为IList
                    {
                        dataSource 
= (IList)(new DataView((DataTable)value));
                        intItemCount 
= dataSource.Count;
                    }

                    
else if(value.GetType() == typeof(DataSet))//数据源是DataSet,转化为IList
                    {
                        dataSource 
= (IList)(new DataView(((DataSet)value).Tables[0]));
                        intItemCount 
= dataSource.Count;
                    }

                    
else
                    
{
                        dataSource 
= (IList)value;
                        intItemCount 
= dataSource.Count;
                    }

                }

                
catch
                
{
                    dataSource 
= null;
                    intItemCount 
=0;
                }

            }

        }


        
protected override void OnLoad(EventArgs e)
        
{
            
if(Visible) 
            
{
                
string page = Context.Request[mstrPageKey];//取得页码
                int index = (page != null? int.Parse(page) : 1;
                index 
= index <= 0 ? 1 : index;
                SetPage(index);
            }

        }


        
public void SetPage(int index) 
        
{
            OnPageIndexChanged(
new DataGridPageChangedEventArgs(null, index));
        }



        
protected override void Render(System.Web.UI.HtmlTextWriter writer)
        
{
            
if(intItemCount == 0)//数据源为空
            {
                writer.Write(mstrEmptyText);
                
return;
            }


            writer.Write(HTML1, mstrPageIndexAlign);
            
if(pagePosition != PagerPosition.Bottom)//页导航元素的位置为Top或者TopAndBottom
            {
                WritePages(writer);
            }

            writer.Write(HTML2);
            
base.Render(writer);
            writer.Write(HTML3, mstrPageIndexAlign);
            
if(pagePosition != PagerPosition.Top)//页导航元素的位置为Bottom或者TopAndBottom
            {
                WritePages(writer);
            }

            writer.Write(HTML4);
        }


        
protected override void OnDataBinding(EventArgs e)
        
{
            
if(blnRealSource)//数据源已分页
            {
                
base.DataSource = dataSource;
            }

            
else//数据源未分页
            {
                
int start = (intCurrentPage - 1* intPageSize;
                
int size = Math.Min(intPageSize, intItemCount - start);

                IList list 
= new ArrayList();

                
for(int i = 0; i < size; i++)
                
{
                    list.Add(dataSource[start 
+ i]);
                }

                
base.DataSource = list;
            }

            
base.OnDataBinding (e);
        }


        
public event DataGridPageChangedEventHandler PageIndexChanged;

        
virtual protected void OnPageIndexChanged(DataGridPageChangedEventArgs e) 
        
{
            
if (PageIndexChanged != null)
            
{
                PageIndexChanged(
this, e);
            }

        }


        
/// <summary>
        
/// 写页导航元素。
        
/// </summary>
        
/// <param name="writer">System.Web.UI.HtmlTextWriter</param>

        virtual protected void WritePages(System.Web.UI.HtmlTextWriter writer)
        
{
            
            
if(pageMode == PagerMode.NextPrev)//页导航元素为上下页
            {
                intPageIndexCount 
= 1;
            }


            intPageIndexCount 
= intPageIndexCount <= 0 ? 1 : intPageIndexCount;
            
//开始的页码
            int start = (intCurrentPage - 1/ intPageIndexCount;
            start 
= start * intPageIndexCount + 1;
            
//结束的页码
            int end = start + intPageIndexCount - 1;
            end 
= end > PageCount ? PageCount : end;

            
//保留PageKey以外的QueryString
            string query = Context.Request.Url.Query.Replace("?","&");
            Regex rx 
= new Regex("&" + mstrPageKey + "=\d+", RegexOptions.None);
            query 
= rx.Replace(query, string.Empty);

            
//写向前的导航元素
            if(start > 1)
            
{
                writer.Write(LINK_PREV, mstrPageKey, (start 
- 1+ query, intPageIndexCount, mstrPrevPageText);
            }


            
if(pageMode != PagerMode.NextPrev)//页导航元素为上下页
            {
                
//写从start到end的页码
                for(int i = start; i <= end; i++)
                
{
                    writer.Write(
"&nbsp;&nbsp;");
                    
if(i == intCurrentPage)//当前页没有联接
                    {
                        writer.Write(i);
                    }

                    
else//不是当前页有链接
                    {    
                        writer.Write(LINK, mstrPageKey, i 
+ query, i);
                    }

                }

            }


            
//写向后的导航元素
            if(end < PageCount)
            
{
                writer.Write(
"&nbsp;&nbsp;");
                writer.Write(LINK_NEXT, mstrPageKey, (end 
+ 1+ query, intPageIndexCount, mstrNextPageText);
            }

        }

    }

}



.aspx
<MYCONTROL:MYREPEATER id="repeater" runat="server" PageKey="Pages" OnPageIndexChanged="PageChanged" EmptyText="nothing">
    
<headertemplate>
        
<table cellpadding="0" cellspacing="0">
            
<tr class="gridHead">
                
<td>Product</td>
                
<td>Name</td>
                
<td>Description</td>
            
</tr>
    
</headertemplate>
    
<itemtemplate>
        
<tr class="gridItem">
            
<td><%# DataBinder.Eval(Container.DataItem, "Id"%></td>
            
<td><href='Items.aspx?productId=<%# DataBinder.Eval(Container.DataItem, "Id") %>'><%# DataBinder.Eval(Container.DataItem, "Name"%></a></td>
            
<td><%# DataBinder.Eval(Container.DataItem, "Description"%></td>
        
</tr>
    
</itemtemplate>
    
<footertemplate>
                    
</table>
                
</footertemplate>
</MYCONTROL:MYREPEATER>


.aspx.cs
protected void PageChanged(object sender, DataGridPageChangedEventArgs e)
        
{
            Common.WebControls.MyRepeater re 
= sender as Common.WebControls.MyRepeater;
            re.CurrentPageIndex 
= e.NewPageIndex;
            DataTable dt 
= new DataTable();
            dt.Columns.Add(
"Id");
            dt.Columns.Add(
"Name");
            dt.Columns.Add(
"Description");

            
for(int i = 0; i < 350; i++)
            
{
                DataRow dr 
= dt.NewRow();
                dr[
0= i.ToString();
                dr[
1= "testName";
                dr[
2= "testDescription";
                dt.Rows.Add(dr);
            }


            re.PrevPageText 
= "上 页";
            re.NextPageText 
= "下 页";
            re.PageMode 
= PagerMode.NextPrev;
            re.PageAlign 
= HorizontalAlign.Right;
            re.PagePosition 
= PagerPosition.Bottom;
            re.PageSize 
= 20;
            re.DataSource 
= dt;
            re.DataBind();
        }


其实和PetShop里的差不多,就加强了一点分页功能。