I created a custom pager function for a content management system I am building. You can create paging for your records using this simple query:
private static string GetPageString(string NewsTitle, string CategoryID)
{
string PageNews = @"
WITH Paging
AS
(
SELECT rn = ROW_NUMBER() OVER (ORDER BY N.date desc),
N.news_id,
N.title,
N.date,
N.published
FROM dbo.news N {0}
)
SELECT TOP (@PageSize)
PG.rn,
PG.news_id,
PG.title,
PG.date,
PG.published
FROM Paging PG
WHERE (PG.rn > ((@PageIndex * @PageSize) - @PageSize)) ORDER BY PG.date desc
SET @TotalRecords = (SELECT COUNT(*) FROM dbo.news N {0})";
string filter = string.Empty;
string joins = string.Empty;
if (!string.IsNullOrEmpty(NewsTitle.Trim()))
filter += " WHERE (N.title LIKE @Title) ";
if (!string.IsNullOrEmpty(CategoryID.Trim()))
{
joins += " INNER JOIN news_category_mapping NCM ON N.news_id = NCM.news_id ";
filter += (!filter.Contains("WHERE")) ? " WHERE (NCM.category_id = @CategoryID) " : " AND (NCM.category_id = @CategoryID) ";
}
PageNews = string.Format(PageNews, joins + filter);
return PageNews;
}
Then use this function to perform the query:
public static NewsCollection GetNewsForPaging(int PageIndex, int PageSize, string NewsTitle, string CategoryID, ref int TotalRecords)
{
NewsCollection newsColl = new NewsCollection();
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(GetPageString(NewsTitle, CategoryID), conn);
cmd.Parameters.AddRange(
new SqlParameter[] {
new SqlParameter("@PageIndex", PageIndex),
new SqlParameter("@PageSize", PageSize),
new SqlParameter("@Title", NewsTitle + "%"),
new SqlParameter("@CategoryID", CategoryID)
});
SqlParameter paramTotalRecords = new SqlParameter("@TotalRecords", SqlDbType.Int);
paramTotalRecords.Direction = ParameterDirection.Output;
cmd.Parameters.Add(paramTotalRecords);
SqlDataReader reader = cmd.ExecuteReader();
do
{
while (reader.Read())
{
News news = new News();
news.NewsID = (int)reader["news_id"];
news.Title = reader["title"].ToString();
news.PostedDate = (DateTime)reader["date"];
news.Published = (bool)reader["published"];
newsColl.Add(news);
}
} while (reader.NextResult());
TotalRecords = (int)paramTotalRecords.Value;
reader.Close();
}
return newsColl;
}
Here is what the call to this function looks like:
private void BindData()
{
int totalRecords = 0;
NewsCollection newsColl = NewsManager.GetNewsForPaging(this.PageIndex, this.PageSize, this.NewsTitle, this.CategoryID, ref totalRecords);
this.TotalRecords = totalRecords;
gvNews.DataSource = newsColl;
gvNews.DataBind();
if (totalRecords == 0)
{
lblResults.Text = "Your search criteria did not return any results";
lbShowAll.Visible = true;
}
else
lbShowAll.Visible = false;
}
The lbShowAll is a link button on the grid view control that looks like this:
<asp:LinkButton ID="lbShowAll" OnCommand="ShowAll" Text="(Return All)" Visible="false" runat="server"/>
Then I added a LinkButton on the GridView user control outside of the GridView itself for referencing:
<asp:LinkButton ID="lbPaging" OnCommand="ChangePage" runat="server" />
Then I added a class to the project called GridViewHelper and here is the function that creates my paging buttons:
public static GridViewRow CreatePagerButtons(GridViewRow row, LinkButton Pager, double TotalRecords, int PageIndex, int PageSize, int PageButtonCount, ref int NextButton, ref int PreviousButton)
{
row.Cells[0].Controls.Clear();
int PageCount = (int)Math.Ceiling(TotalRecords / PageSize);
int startCount = 0;
bool IsPageIndex = false;
bool IsNextPrevious = false;
if (PageIndex == NextButton)
{
startCount = NextButton;
IsNextPrevious = true;
}
else if (PageIndex == PreviousButton)
{
startCount = PageIndex - PageButtonCount;
IsNextPrevious = true;
}
else if ((PageIndex != NextButton) && (PageIndex != PreviousButton))
{
startCount = PageIndex;
IsPageIndex = true;
}
int linkCount = (!startCount.Equals(0)) ? startCount : 1;
if (IsPageIndex)
{
if (startCount > PageButtonCount)
{
int mod = (PageIndex % PreviousButton);
startCount = (startCount - mod) + 1;
HyperLink hlPrevious = new HyperLink();
hlPrevious.Text = "...";
hlPrevious.NavigateUrl = "javascript:__doPostBack('" + Pager.ClientID + "','" + (startCount - 1).ToString() + "');";
row.Cells[0].Controls.Add(hlPrevious);
}
else
startCount = 1;
linkCount = startCount;
for (int i = 0; i < PageCount; i++)
{
HyperLink hl = new HyperLink();
if (linkCount == PageIndex)
{
hl.ForeColor = System.Drawing.Color.FromArgb(0, 36, 93, 117);
hl.Font.Bold = false;
hl.NavigateUrl = "";
}
else
hl.NavigateUrl = "javascript:__doPostBack('" + Pager.ClientID + "','" + linkCount.ToString() + "');";
hl.Text = linkCount.ToString();
row.Cells[0].Controls.Add(hl);
if (linkCount == PageCount)
break;
if (i.Equals(PageButtonCount))
{
HyperLink hlNext = new HyperLink();
hlNext.Text = "...";
hlNext.NavigateUrl = "javascript:__doPostBack('" + Pager.ClientID + "','" + (linkCount + 1).ToString() + "');";
row.Cells[0].Controls.Add(hlNext);
NextButton = linkCount + 1;
break;
}
linkCount++;
}
}
else if (IsNextPrevious)
{
if (startCount > PageButtonCount)
{
HyperLink hlPrevious = new HyperLink();
hlPrevious.Text = "...";
hlPrevious.NavigateUrl = "javascript:__doPostBack('" + Pager.ClientID + "','" + (startCount - 1).ToString() + "');";
row.Cells[0].Controls.Add(hlPrevious);
PreviousButton = startCount - 1;
}
for (int i = 0; i < PageCount; i++)
{
HyperLink hl = new HyperLink();
if (linkCount == PageIndex)
{
hl.ForeColor = System.Drawing.Color.FromArgb(0, 36, 93, 117);
hl.Font.Bold = false;
hl.NavigateUrl = "";
}
else
hl.NavigateUrl = "javascript:__doPostBack('" + Pager.ClientID + "','" + linkCount.ToString() + "');";
hl.Text = linkCount.ToString();
row.Cells[0].Controls.Add(hl);
if (linkCount == PageCount)
break;
if (i.Equals(PageButtonCount))
{
HyperLink hlNext = new HyperLink();
hlNext.Text = "...";
hlNext.NavigateUrl = "javascript:__doPostBack('" + Pager.ClientID + "','" + (linkCount + 1).ToString() + "');";
row.Cells[0].Controls.Add(hlNext);
NextButton = linkCount + 1;
break;
}
linkCount++;
}
}
return row;
}
In the code behind file for the grid view, you will need to store certain values in view state like PageSize, PageIndex, NextButton, PreviousButton, PageButtonCount. Here is what the function looks like in the code behind of the grid view:
protected void gvNewsPreRender(object sender, EventArgs e)
{
if (gvNews.Controls.Count > 0)
{
gvNews.BottomPagerRow.Visible = true;
gvNews.TopPagerRow.Visible = true;
GridViewRow gvrBottom = gvNews.BottomPagerRow;
int nextButton = this.NextButton;
int prevButton = this.PreviousButton;
GridViewHelper.CreatePagerButtons(gvrBottom, lbPaging, this.TotalRecords, this.PageIndex, this.PageSize, this.PageButtonCount, ref nextButton, ref prevButton);
this.NextButton = nextButton;
this.PreviousButton = prevButton;
GridViewRow gvrTop = gvNews.TopPagerRow;
GridViewHelper.CreateAlphaPagerButtons(gvrTop, lbAlpha, this.Letter);
}
}
I also created a top pager with the letters of the alphabet and that is the bottom function that you see.
Anyways, I hope this helps you in your journey to custom paging.