Repeater和GridView支持DataPager分页做法

作者:袖梨 2022-06-25

改造办法是自己写一个控件,让它继承GridView或Repeater,并实现IPageableItemContainer 接口。下面要发的是国外某高手写的代码,测试有效。具体使用的时候,要建一个类库项目,把代码编译成dll后,就可以添加到VS的工具箱里了!

一、自定义Repeater

 代码如下 复制代码

using System.Web.UI;
using System.Web.UI.WebControls;

namespace WYJ.Web.Controls
{
    ///


    /// Repeater with support for DataPager
    ///

    [ToolboxData("<{0}:DataPagerRepeater runat=server PersistentDataSource=true>")]
    public class DataPagerRepeater : Repeater, System.Web.UI.WebControls.IPageableItemContainer, INamingContainer
    {
        ///
        /// Number of rows to show
        ///

        public int MaximumRows { get { return ViewState["MaximumRows"] != null ? (int)ViewState["MaximumRows"] : -1; } }

        ///


        /// First row to show
        ///

        public int StartRowIndex { get { return ViewState["StartRowIndex"] != null ? (int)ViewState["StartRowIndex"] : -1; } }

        ///


        /// Total rows. When PagingInDataSource is set to true you must get the total records from the datasource (without paging) at the FetchingData event
        /// When PagingInDataSource is set to true you also need to set this when you load the data the first time.
        ///

        public int TotalRows { get { return ViewState["TotalRows"] != null ? (int)ViewState["TotalRows"] : -1; } set { ViewState["TotalRows"] = value; } }

        ///


        /// If repeater should store data source in view state. If false you need to get and bind data at post back. When using a connected data source this is handled by the data source. 
        ///

        public bool PersistentDataSource
        {
            get { return ViewState["PersistentDataSource"] != null ? (bool)ViewState["PersistentDataSource"] : true; }
            set { ViewState["PersistentDataSource"] = value; }
        }
        ///
        /// Set to true if you want to handle paging in the data source.
        /// Ex if you are selecting data from the database and only select the current rows
        /// you must set this property to true and get and rebind data at the FetchingData event.
        /// If this is true you must also set the TotalRecords property at the FetchingData event.    
        ///

        ///
        ///
        public bool PagingInDataSource
        {
            get { return ViewState["PageingInDataSource"] != null ? (bool)ViewState["PageingInDataSource"] : false; }
            set { ViewState["PageingInDataSource"] = value; }
        }
        ///
        /// Checks if you need to rebind data source at postback
        ///

        public bool NeedsDataSource
        {
            get
            {
                if (PagingInDataSource)
                    return true;
                if (IsBoundUsingDataSourceID == false && !Page.IsPostBack)
                    return true;
                if (IsBoundUsingDataSourceID == false && PersistentDataSource == false && Page.IsPostBack)
                    return true;
                else
                    return false;
            }
        }

        ///


        /// Loading ViewState
        ///

        ///
        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);

            //if (Page.IsPostBack)
            //{

            //    if (!IsBoundUsingDataSourceID && PersistentDataSource && ViewState["DataSource"] != null)
            //    {
            //        this.DataSource = ViewState["DataSource"];
            //        this.DataBind(true);
            //    }
            //    if (IsBoundUsingDataSourceID)
            //    {
            //        this.DataBind();
            //    }
            //}
        }

        protected override void OnLoad(System.EventArgs e)
        {
            if (Page.IsPostBack)
            {
                if (NeedsDataSource && FetchingData != null)
                {
                    if (PagingInDataSource)
                    {
                        SetPageProperties(StartRowIndex, MaximumRows, true);
                    }
                    FetchingData(this, null);
                }

                if (!IsBoundUsingDataSourceID && PersistentDataSource && ViewState["DataSource"] != null)
                {
                    this.DataSource = ViewState["DataSource"];
                    this.DataBind();
                }
                if (IsBoundUsingDataSourceID)
                {
                    this.DataBind();
                }

            }

            base.OnLoad(e);

        }


        ///


        /// Method used by pager to set totalrecords
        ///

        /// startRowIndex
        /// maximumRows
        /// databind
        public void SetPageProperties(int startRowIndex, int maximumRows, bool databind)
        {
            ViewState["StartRowIndex"] = startRowIndex;
            ViewState["MaximumRows"] = maximumRows;

            if (TotalRows > -1)
            {
                if (TotalRowCountAvailable != null)
                {
                    TotalRowCountAvailable(this, new PageEventArgs((int)ViewState["StartRowIndex"], (int)ViewState["MaximumRows"], TotalRows));
                }
            }
        }
        ///


        /// OnDataPropertyChanged
        ///

        protected override void OnDataPropertyChanged()
        {
            if (MaximumRows != -1 || IsBoundUsingDataSourceID)
            {
                this.RequiresDataBinding = true;
               
            }
           
                base.OnDataPropertyChanged();
        }

        ///


        /// Renders only current items selected by pager
        ///

        ///
        protected override void RenderChildren(HtmlTextWriter writer)
        {
            if (!PagingInDataSource && MaximumRows != -1)
            {
                foreach (RepeaterItem item in this.Items)
                {
                    if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
                    {
                        item.Visible = false;
                        if (item.ItemIndex >= (int)ViewState["StartRowIndex"] && item.ItemIndex < ((int)ViewState["StartRowIndex"] + (int)ViewState["MaximumRows"]))
                        {
                            item.Visible = true;
                        }
                    }
                    else
                    {
                        item.Visible = true;
                    }
                }
            }
            base.RenderChildren(writer);
        }

        ///


        /// Get Data
        ///

        ///
        protected override System.Collections.IEnumerable GetData()
        {
            System.Collections.IEnumerable dataObjects = base.GetData();

            if (dataObjects == null && this.DataSource != null)
            {
                if (this.DataSource is System.Collections.IEnumerable)
                    dataObjects = (System.Collections.IEnumerable)this.DataSource;
                else
                    dataObjects = ((System.ComponentModel.IListSource)this.DataSource).GetList();
            }

            if (!PagingInDataSource && MaximumRows != -1 && dataObjects != null)
            {
                int i = -1;

                if (dataObjects != null)
                {
                    i = 0;
                    foreach (object o in dataObjects)
                    {
                        i++;
                    }

                }

                ViewState["TotalRows"] = i;

                if (!IsBoundUsingDataSourceID && PersistentDataSource)
                    ViewState["DataSource"] = this.DataSource;

                SetPageProperties(StartRowIndex, MaximumRows, true);
               
            }

            if (PagingInDataSource && !Page.IsPostBack)
            {
                SetPageProperties(StartRowIndex, MaximumRows, true);
            }

            return dataObjects;
        }

 

        ///


        /// Event when pager/repeater have counted total rows
        ///

        public event System.EventHandler TotalRowCountAvailable;

        ///


        /// Event when repeater gets the data on postback
        ///

        public event System.EventHandler FetchingData;

    }

}

 

 

ASPX页面要做的事情(以我网站的留言板为例):

首先得把标签注册进来

 代码如下 复制代码

<%@ Register Assembly="WYJ.Web.Controls" Namespace="WYJ.Web.Controls" TagPrefix="WYJ" %>

然后添加我们的Repeater

 代码如下 复制代码


   
       


           

               

                    <%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Posttime.ToString("HH:mm") %>

               

                    <%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Posttime.ToString("dd") %>
               

               

                    <%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Posttime.ToString("MMM", new CultureInfo("en-US")).ToUpper() %><%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Posttime.ToString(" yyyy") %>

           

           

               


                                            name="<%# GeekStudio.Common.IdEncryptor.EncodeId(((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Id) %>">
                        <%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Username %>


               

                    <%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Content %>
               

           

       

   

 

 

之后添加.NET自带的DataPager,并自定义一些分页样式

 代码如下 复制代码


   

        共<%=Math.Ceiling((double)DataPager1.TotalRowCount / DataPager1.PageSize)%>页,<%=DataPager1.TotalRowCount%>条记录,每页显示
        <asp:LinkButton ID="lnkbtn10" CssClass="currentpagesize" runat="server" OnClick="lnkbtn10_Click">10
        20
        30
   

   
       
                            ShowPreviousPageButton="False" FirstPageText="首页" />
           
           
           
                            ShowPreviousPageButton="False" LastPageText="尾页" />
       

   

 

后台代码:

分页部分不需要代码。下面发的代码是切换每页显示数量的:

 代码如下 复制代码

protected void lnkbtn10_Click(object sender, EventArgs e)
{
    DataPager1.PageSize = 10;
    lnkbtn10.CssClass = "currentpagesize";
    lnkbtn20.CssClass = "";
    lnkbtn30.CssClass = "";
}

protected void lnkbtn20_Click(object sender, EventArgs e)
{
    DataPager1.PageSize = 20;
    lnkbtn20.CssClass = "currentpagesize";
    lnkbtn10.CssClass = "";
    lnkbtn30.CssClass = "";
}

protected void lnkbtn30_Click(object sender, EventArgs e)
{
    DataPager1.PageSize = 30;
    lnkbtn30.CssClass = "currentpagesize";
    lnkbtn10.CssClass = "";
    lnkbtn20.CssClass = "";
}

 

 

二、自定义GridView

 代码如下 复制代码

using System;
using System.Collections;
using System.Web.UI.WebControls;

namespace WYJ.Web.Controls
{
    ///


    /// DataPagerGridView is a custom control that implements GrieView and IPageableItemContainer
    ///

    public class DataPagerGridView : GridView, IPageableItemContainer
    {
        public DataPagerGridView()
            : base()
        {
            PagerSettings.Visible = false;
        }

        ///


        /// TotalRowCountAvailable event key
        ///

        private static readonly object EventTotalRowCountAvailable = new object();

        ///


        /// Call base control's CreateChildControls method and determine the number of rows in the source
        /// then fire off the event with the derived data and then we return the original result.
        ///

        ///
        ///
        ///
        protected override int CreateChildControls(IEnumerable dataSource, bool dataBinding)
        {
            int rows = base.CreateChildControls(dataSource, dataBinding);

            //  if the paging feature is enabled, determine the total number of rows in the datasource
            if (this.AllowPaging)
            {
                //  if we are databinding, use the number of rows that were created, otherwise cast the datasource to an Collection and use that as the count
                int totalRowCount = dataBinding ? rows : ((ICollection)dataSource).Count;

                //  raise the row count available event
                IPageableItemContainer pageableItemContainer = this as IPageableItemContainer;
                this.OnTotalRowCountAvailable(new PageEventArgs(pageableItemContainer.StartRowIndex, pageableItemContainer.MaximumRows, totalRowCount));

                //  make sure the top and bottom pager rows are not visible
                if (this.TopPagerRow != null)
                    this.TopPagerRow.Visible = false;

                if (this.BottomPagerRow != null)
                    this.BottomPagerRow.Visible = false;
            }
            return rows;
        }

        ///


        /// Set the control with appropriate parameters and bind to right chunk of data.
        ///

        ///
        ///
        ///
        void IPageableItemContainer.SetPageProperties(int startRowIndex, int maximumRows, bool databind)
        {
            int newPageIndex = (startRowIndex / maximumRows);
            this.PageSize = maximumRows;

            if (this.PageIndex != newPageIndex)
            {
                bool isCanceled = false;
                if (databind)
                {
                    //  create the event arguments and raise the event
                    GridViewPageEventArgs args = new GridViewPageEventArgs(newPageIndex);
                    this.OnPageIndexChanging(args);

                    isCanceled = args.Cancel;
                    newPageIndex = args.NewPageIndex;
                }

                //  if the event wasn't cancelled change the paging values
                if (!isCanceled)
                {
                    this.PageIndex = newPageIndex;

                    if (databind)
                        this.OnPageIndexChanged(EventArgs.Empty);
                }
                if (databind)
                    this.RequiresDataBinding = true;
            }
        }

        ///


        /// IPageableItemContainer's StartRowIndex = PageSize * PageIndex properties
        ///

        int IPageableItemContainer.StartRowIndex
        {
            get { return this.PageSize * this.PageIndex; }
        }

        ///


        /// IPageableItemContainer's MaximumRows  = PageSize property
        ///

        int IPageableItemContainer.MaximumRows
        {
            get { return this.PageSize; }
        }

        ///


        ///
        ///

        event EventHandler IPageableItemContainer.TotalRowCountAvailable
        {
            add { base.Events.AddHandler(DataPagerGridView.EventTotalRowCountAvailable, value); }
            remove { base.Events.RemoveHandler(DataPagerGridView.EventTotalRowCountAvailable, value); }
        }

        ///


        ///
        ///

        ///
        protected virtual void OnTotalRowCountAvailable(PageEventArgs e)
        {
            EventHandler handler = (EventHandler)base.Events[DataPagerGridView.EventTotalRowCountAvailable];
            if (handler != null)
            {
                handler(this, e);
            }
        }
    }
}

用法与Repeater类似,不多发了~

相关文章

精彩推荐