asp.net has Repeater and GridView support DataPager paging

  • 2020-05-17 05:07:24
  • OfStack

The solution is to write your own control, let it inherit from GridView or Repeater, and implement the IPageableItemContainer interface. What should send below is the code that some foreign ace writes, the test is effective. When you use it, you should build a class library project, compile the code into dll, and then you can add it to VS's toolbox!
1. Customize Repeater
 
using System.Web.UI; 
using System.Web.UI.WebControls; 
namespace WYJ.Web.Controls 
{ 
/// <summary> 
/// Repeater with support for DataPager 
/// </summary> 
[ToolboxData("<{0}:DataPagerRepeater runat=server PersistentDataSource=true></{0}:DataPagerRepeater>")] 
public class DataPagerRepeater : Repeater, System.Web.UI.WebControls.IPageableItemContainer, INamingContainer 
{ 
/// <summary> 
/// Number of rows to show 
/// </summary> 
public int MaximumRows { get { return ViewState["MaximumRows"] != null ? (int)ViewState["MaximumRows"] : -1; } } 
/// <summary> 
/// First row to show 
/// </summary> 
public int StartRowIndex { get { return ViewState["StartRowIndex"] != null ? (int)ViewState["StartRowIndex"] : -1; } } 
/// <summary> 
/// 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. 
/// </summary> 
public int TotalRows { get { return ViewState["TotalRows"] != null ? (int)ViewState["TotalRows"] : -1; } set { ViewState["TotalRows"] = value; } } 
/// <summary> 
/// 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. 
/// </summary> 
public bool PersistentDataSource 
{ 
get { return ViewState["PersistentDataSource"] != null ? (bool)ViewState["PersistentDataSource"] : true; } 
set { ViewState["PersistentDataSource"] = value; } 
} 
/// <summary> 
/// 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. 
/// </summary> 
/// <seealso cref="FetchingData"/> 
/// <seealso cref="TotalRows"/> 
public bool PagingInDataSource 
{ 
get { return ViewState["PageingInDataSource"] != null ? (bool)ViewState["PageingInDataSource"] : false; } 
set { ViewState["PageingInDataSource"] = value; } 
} 
/// <summary> 
/// Checks if you need to rebind data source at postback 
/// </summary> 
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; 
} 
} 
/// <summary> 
/// Loading ViewState 
/// </summary> 
/// <param name="savedState"></param> 
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); 
} 
/// <summary> 
/// Method used by pager to set totalrecords 
/// </summary> 
/// <param name="startRowIndex">startRowIndex</param> 
/// <param name="maximumRows">maximumRows</param> 
/// <param name="databind">databind</param> 
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)); 
} 
} 
} 
/// <summary> 
/// OnDataPropertyChanged 
/// </summary> 
protected override void OnDataPropertyChanged() 
{ 
if (MaximumRows != -1 || IsBoundUsingDataSourceID) 
{ 
this.RequiresDataBinding = true; 
} 
base.OnDataPropertyChanged(); 
} 
/// <summary> 
/// Renders only current items selected by pager 
/// </summary> 
/// <param name="writer"></param> 
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); 
} 
/// <summary> 
/// Get Data 
/// </summary> 
/// <returns></returns> 
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; 
} 
/// <summary> 
/// Event when pager/repeater have counted total rows 
/// </summary> 
public event System.EventHandler<PageEventArgs> TotalRowCountAvailable; 
/// <summary> 
/// Event when repeater gets the data on postback 
/// </summary> 
public event System.EventHandler<PageEventArgs> FetchingData; 
} 
} 

What to do on the ASPX page (take my message board for example) :
You have to register the label first
<%@ Register Assembly="WYJ.Web.Controls" Namespace="WYJ.Web.Controls" TagPrefix="WYJ" %> 

Then add our Repeater
 
<WYJ:DataPagerRepeater ID="rptLeaveword" runat="server" PersistentDataSource="true"> 
<ItemTemplate> 
<div class="leavewordentry"> 
<div class="datebox"> 
<div class="time"> 
<%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Posttime.ToString("HH:mm") %></div> 
<div class="day"> 
<%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Posttime.ToString("dd") %> 
</div> 
<div class="month"> 
<%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Posttime.ToString("MMM", new CultureInfo("en-US")).ToUpper() %><%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Posttime.ToString(" yyyy") %></div> 
</div> 
<div class="contentbox"> 
<h2 class="username"> 
<a id="<%# GeekStudio.Common.IdEncryptor.EncodeId(((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Id) %>" 
name="<%# GeekStudio.Common.IdEncryptor.EncodeId(((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Id) %>"> 
<%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Username %></a></h2> 
<div class="lvwordcontent"> 
<%# ((GeekStudio.ORM.Model.Leaveword)Container.DataItem).Content %> 
</div> 
</div> 
</div> 
</ItemTemplate> 
</WYJ:DataPagerRepeater> 

Then add DataPager, which comes with.NET, and customize some pagination styles
 
<div class="pager"> 
<div class="fr"> 
 A total of <%=Math.Ceiling((double)DataPager1.TotalRowCount / DataPager1.PageSize)%> Page, <%=DataPager1.TotalRowCount%> A record displayed on each page  
<asp:LinkButton ID="lnkbtn10" CssClass="currentpagesize" runat="server" OnClick="lnkbtn10_Click">10</asp:LinkButton> 
<asp:LinkButton ID="lnkbtn20" runat="server" OnClick="lnkbtn20_Click">20</asp:LinkButton> 
<asp:LinkButton ID="lnkbtn30" runat="server" OnClick="lnkbtn30_Click">30</asp:LinkButton> 
</div> 
<asp:DataPager ID="DataPager1" PagedControlID="rptLeaveword" runat="server"> 
<Fields> 
<asp:NextPreviousPagerField ShowFirstPageButton="True" ShowNextPageButton="False" 
ShowPreviousPageButton="False" FirstPageText=" Home page " /> 
<asp:NextPreviousPagerField ShowNextPageButton="False" ButtonType="Image" PreviousPageImageUrl="~/Images/icons/pagerprevious.png" /> 
<asp:NumericPagerField CurrentPageLabelCssClass="current" /> 
<asp:NextPreviousPagerField ShowPreviousPageButton="False" ButtonType="Image" NextPageImageUrl="~/Images/icons/pagernext.png" /> 
<asp:NextPreviousPagerField ShowLastPageButton="True" ShowNextPageButton="False" 
ShowPreviousPageButton="False" LastPageText=" back " /> 
</Fields> 
</asp:DataPager> 
</div> 

Background code:
No code is required for the paging section. The following code is to switch the number of display per page:
 
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 = ""; 
} 

2. Customize GridView
 
using System; 
using System.Collections; 
using System.Web.UI.WebControls; 
namespace WYJ.Web.Controls 
{ 
/// <summary> 
/// DataPagerGridView is a custom control that implements GrieView and IPageableItemContainer 
/// </summary> 
public class DataPagerGridView : GridView, IPageableItemContainer 
{ 
public DataPagerGridView() 
: base() 
{ 
PagerSettings.Visible = false; 
} 
/// <summary> 
/// TotalRowCountAvailable event key 
/// </summary> 
private static readonly object EventTotalRowCountAvailable = new object(); 
/// <summary> 
/// 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. 
/// </summary> 
/// <param name="dataSource"></param> 
/// <param name="dataBinding"></param> 
/// <returns></returns> 
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; 
} 
/// <summary> 
/// Set the control with appropriate parameters and bind to right chunk of data. 
/// </summary> 
/// <param name="startRowIndex"></param> 
/// <param name="maximumRows"></param> 
/// <param name="databind"></param> 
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; 
} 
} 
/// <summary> 
/// IPageableItemContainer's StartRowIndex = PageSize * PageIndex properties 
/// </summary> 
int IPageableItemContainer.StartRowIndex 
{ 
get { return this.PageSize * this.PageIndex; } 
} 
/// <summary> 
/// IPageableItemContainer's MaximumRows = PageSize property 
/// </summary> 
int IPageableItemContainer.MaximumRows 
{ 
get { return this.PageSize; } 
} 
/// <summary> 
/// 
/// </summary> 
event EventHandler<PageEventArgs> IPageableItemContainer.TotalRowCountAvailable 
{ 
add { base.Events.AddHandler(DataPagerGridView.EventTotalRowCountAvailable, value); } 
remove { base.Events.RemoveHandler(DataPagerGridView.EventTotalRowCountAvailable, value); } 
} 
/// <summary> 
/// 
/// </summary> 
/// <param name="e"></param> 
protected virtual void OnTotalRowCountAvailable(PageEventArgs e) 
{ 
EventHandler<PageEventArgs> handler = (EventHandler<PageEventArgs>)base.Events[DataPagerGridView.EventTotalRowCountAvailable]; 
if (handler != null) 
{ 
handler(this, e); 
} 
} 
} 
} 

The usage is similar to Repeater

Related articles: