Skip to main content
Code Review

Return to Revisions

3 of 3
replaced http://stackoverflow.com/ with https://stackoverflow.com/

Custom Paging in ASP.Net Web Application

I have following code for doing custom paging from an asp.net web application.

Points of interest

  1. It uses Link Buttons as suggested in https://stackoverflow.com/questions/14335067/passing-search-parameters-to-same-page-when-hyperlink-clicked
  2. The link buttons are added in Page_Load itself as listed in https://stackoverflow.com/questions/14364332/dynamic-controls-event-handlers-working
  3. It is made as user control for reuse

QUESTIONS

  1. Is there any pitfalls in this approach?
  2. Is there any improvement suggestions?

User Control Markup

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="PagingUserControl.ascx.cs"
Inherits="PagingTestWebApplication.PagingUserControl" %>
<div class="pagingSection" id="pagingSection" runat="server">
<asp:LinkButton ID="lnkPrevious" runat="server" CssClass='page-numbers prev' Visible="false" OnClick="LinkButton_Click">Prev</asp:LinkButton>
<asp:LinkButton ID="lnkFirst" runat="server" CssClass='page-numbers' Visible="false"
 OnClick="LinkButton_Click">1</asp:LinkButton>
<asp:Label runat="server" ID="lblFirstDots" CssClass="page-numbers prev" Visible="false"
 Text="..."></asp:Label>
<asp:PlaceHolder ID="plhDynamicLink" runat="server"></asp:PlaceHolder>
<asp:Label runat="server" ID="lblSecondDots" Visible="false" CssClass="page-numbers prev"
 Text="..."></asp:Label>
<asp:LinkButton ID="lnkLast" runat="server" CssClass='page-numbers' Visible="false"
 OnClick="LinkButton_Click">Last</asp:LinkButton>
<asp:LinkButton ID="lnkNext" runat="server" CssClass='page-numbers next' Visible="false" OnClick="LinkButton_Click">Next</asp:LinkButton>
 </div>

User Control Code Behind

public partial class PagingUserControl : System.Web.UI.UserControl
{
 protected void Page_Load(object sender, EventArgs e)
 {
 }
 public int PreviousIndex { get; set; }
 public int CurrentClickedIndex { get; set; }
 public event EventHandler PaginationLinkClicked;
 protected void LinkButton_Click(object sender, EventArgs e)
 {
 //Assumption: Text of the LinkButton will be same as index
 LinkButton clickedLinkButton = (LinkButton)sender;
 if (String.Equals(clickedLinkButton.Text, "Next"))
 {
 //Next Page index will be one greater than current
 //Note: If the current index is the last page, "Next" control will be in disabled state
 CurrentClickedIndex = PreviousIndex + 1;
 }
 else if (String.Equals(clickedLinkButton.Text, "Prev"))
 {
 //Previous Page index will be one less than current
 //Note: If the current index is the first page, "Prev" control will be in disabled state
 CurrentClickedIndex = PreviousIndex - 1;
 }
 else
 {
 CurrentClickedIndex = Convert.ToInt32(clickedLinkButton.Text, CultureInfo.InvariantCulture);
 }
 //Raise event
 if (this.PaginationLinkClicked != null)
 {
 this.PaginationLinkClicked(clickedLinkButton, e);
 }
 }
 public void PreAddAllLinks(int tableDataCount,int pageSize, int currentIndex)
 {
 if (tableDataCount > 0)
 {
 PagingInfo info = PagingHelper.GetAllLinks(tableDataCount, pageSize, currentIndex);
 //Remove all controls from the placeholder
 plhDynamicLink.Controls.Clear();
 if (info.PaginationLinks != null)
 {
 foreach (LinkButton link in info.PaginationLinks)
 {
 //Adding Event handler must be done inside Page_Laod /Page_Init
 link.Click += new EventHandler(LinkButton_Click);
 //Validation controls should be executed before link click.
 link.ValidationGroup = "Search";
 this.plhDynamicLink.Controls.Add(link);
 }
 }
 }
 }
 public void AddPageLinks(int tableDataCount, int pageSize, int index)
 {
 if (tableDataCount > 0)
 {
 pagingSection.Visible = true;
 PagingInfo info = PagingHelper.GetPageLinks(tableDataCount, pageSize, index);
 //Remove all controls from the placeholder
 plhDynamicLink.Controls.Clear();
 if (info.PaginationLinks != null)
 {
 lnkPrevious.Visible = info.PaginationLinks.Count > 0 ? true : false;
 lnkNext.Visible = info.PaginationLinks.Count > 0 ? true : false;
 foreach (LinkButton link in info.PaginationLinks)
 {
 //Validation controls should be executed before link click.
 link.ValidationGroup = "Search";
 this.plhDynamicLink.Controls.Add(link);
 }
 }
 
 //Dots visiblity
 if (info.IsEndDotsVisible != null)
 {
 lblSecondDots.Visible = Convert.ToBoolean(info.IsEndDotsVisible, CultureInfo.InvariantCulture);
 }
 else
 {
 lblSecondDots.Visible = false;
 }
 if (info.IsStartDotsVisible != null)
 {
 lblFirstDots.Visible = Convert.ToBoolean(info.IsStartDotsVisible, CultureInfo.InvariantCulture);
 }
 else
 {
 lblFirstDots.Visible = false;
 }
 //First and Last Links
 if (info.IsFirstLinkVisible != null)
 {
 lnkFirst.Visible = Convert.ToBoolean(info.IsFirstLinkVisible, CultureInfo.InvariantCulture);
 }
 else
 {
 lnkFirst.Visible = false;
 }
 if (info.IsLastLinkVisible != null)
 {
 lnkLast.Visible = Convert.ToBoolean(info.IsLastLinkVisible, CultureInfo.InvariantCulture);
 lnkLast.Text = info.NumberOfPagesRequired.ToString(CultureInfo.InvariantCulture);
 }
 else
 {
 lnkLast.Visible = false;
 }
 //For first page, there is no previous
 if (index != 1 && info.NumberOfPagesRequired != 1)
 {
 lnkPrevious.Enabled = true;
 }
 else
 {
 lnkPrevious.Enabled = false;
 }
 //For last page there is no Next
 if (index != info.NumberOfPagesRequired && info.NumberOfPagesRequired != 1)
 {
 lnkNext.Enabled = true;
 }
 else
 {
 lnkNext.Enabled = false;
 }
 }
 else
 {
 pagingSection.Visible = false;
 }
 }
 }

DTO

public class PagingInfo
{
 public Collection<LinkButton> PaginationLinks { get; set; }
 public bool? IsEndDotsVisible { get; set; }
 public bool? IsStartDotsVisible { get; set; }
 public bool? IsFirstLinkVisible { get; set; }
 public bool? IsLastLinkVisible { get; set; }
 public int NumberOfPagesRequired { get; set; }
}

Helper

public static class PagingHelper
{
 public static PagingInfo GetAllLinks(int totalRecordsInTable, int pageSize, int previousIndex)
 {
 
 string LinkButtonIDPrefix = "lnK";
 PagingInfo pagingInfo = new PagingInfo();
 pagingInfo.PaginationLinks = new Collection<LinkButton>();
 if (totalRecordsInTable > 0)
 {
 int itemsBeforePage = 4;
 int itemsAfterPage = 2;
 int dynamicDisplayCount = itemsBeforePage + 1 + itemsAfterPage;
 Double numberOfPagesRequired = Convert.ToDouble(totalRecordsInTable / pageSize);
 if (totalRecordsInTable % pageSize != 0)
 {
 numberOfPagesRequired = numberOfPagesRequired + 1;
 }
 if (numberOfPagesRequired == 0)
 {
 numberOfPagesRequired = 1;
 }
 //Note: This function adds only the probable Links that the user can click (based on previous click).
 //This is needed sice dynamic controls need to be added while Page_Load itself for event handlers to work
 //In case of any bug, easiest way is add all links from 1 to numberOfPagesRequired
 //Following is an optimized way
 int endOfLeftPart = dynamicDisplayCount;
 //User may click "1". So the first 7 items may be required for display. Hence add them for event handler purpose
 for (int i = 1; i <= endOfLeftPart; i++)
 {
 //Create dynamic Links 
 LinkButton lnk = new LinkButton();
 lnk.ID = LinkButtonIDPrefix + i.ToString(CultureInfo.InvariantCulture);
 lnk.Text = i.ToString(CultureInfo.InvariantCulture);
 pagingInfo.PaginationLinks.Add(lnk);
 }
 int startOfRighPart = Convert.ToInt32(numberOfPagesRequired) - dynamicDisplayCount + 1;
 //User may click the last link. So the last 7 items may be required for display. Hence add them for event handler purpose
 for (int i = startOfRighPart; i <= Convert.ToInt32(numberOfPagesRequired); i++)
 {
 //Links already added should not be added again
 if (i > endOfLeftPart)
 {
 //Create dynamic Links 
 LinkButton lnk = new LinkButton();
 lnk.ID = LinkButtonIDPrefix + i.ToString(CultureInfo.InvariantCulture);
 lnk.Text = i.ToString(CultureInfo.InvariantCulture);
 pagingInfo.PaginationLinks.Add(lnk);
 }
 }
 //User may click on 4 items before current index as well as 2 items after current index
 for (int i = (previousIndex - itemsBeforePage); i <= (previousIndex + itemsAfterPage); i++)
 {
 //Links already added should not be added again
 if (i > endOfLeftPart && i < startOfRighPart)
 {
 //Create dynamic Links 
 LinkButton lnk = new LinkButton();
 lnk.ID = LinkButtonIDPrefix + i.ToString(CultureInfo.InvariantCulture);
 lnk.Text = i.ToString(CultureInfo.InvariantCulture);
 pagingInfo.PaginationLinks.Add(lnk);
 }
 }
 }
 return pagingInfo;
 }
 public static PagingInfo GetPageLinks(int totalRecordsInTable, int pageSize, int currentIndex)
 {
 string LinkButtonIDPrefix = "lnK";
 PagingInfo pagingInfo = new PagingInfo();
 pagingInfo.PaginationLinks = new Collection<LinkButton>();
 if (totalRecordsInTable > 0)
 {
 int itemsBeforePage = 4;
 int itemsAfterPage = 2;
 int dynamicDisplayCount = itemsBeforePage + 1 + itemsAfterPage;
 Double numberOfPagesRequired = Convert.ToDouble(totalRecordsInTable / pageSize);
 if (totalRecordsInTable % pageSize != 0)
 {
 numberOfPagesRequired = numberOfPagesRequired + 1;
 }
 if (numberOfPagesRequired == 0)
 {
 numberOfPagesRequired = 1;
 }
 //Generate dynamic paging 
 int start;
 if (currentIndex <= (itemsBeforePage + 1))
 {
 start = 1;
 }
 else
 {
 start = currentIndex - itemsBeforePage;
 }
 int lastAddedLinkIndex = 0;
 int? firtsAddedLinkIndex = null;
 for (int i = start; i < start + dynamicDisplayCount; i++)
 {
 if (i > numberOfPagesRequired)
 {
 break;
 }
 //Create dynamic Links 
 LinkButton lnk = new LinkButton();
 lnk.ID = LinkButtonIDPrefix + i.ToString(CultureInfo.InvariantCulture);
 lnk.Text = i.ToString(CultureInfo.InvariantCulture);
 lastAddedLinkIndex = i;
 if (firtsAddedLinkIndex == null)
 {
 firtsAddedLinkIndex = i;
 }
 //Check whetehr current page
 if (i == currentIndex)
 {
 lnk.CssClass = "page-numbers current";
 }
 else
 {
 lnk.CssClass = "page-numbers";
 }
 pagingInfo.PaginationLinks.Add(lnk);
 }
 if (numberOfPagesRequired > dynamicDisplayCount)
 {
 //Set dots (ellipse) visibility
 pagingInfo.IsEndDotsVisible = lastAddedLinkIndex == numberOfPagesRequired ? false : true;
 pagingInfo.IsStartDotsVisible = firtsAddedLinkIndex <= 2 ? false : true;
 //First and Last Page Links
 pagingInfo.IsLastLinkVisible = lastAddedLinkIndex == numberOfPagesRequired ? false : true;
 pagingInfo.IsFirstLinkVisible = firtsAddedLinkIndex == 1 ? false : true;
 }
 pagingInfo.NumberOfPagesRequired = Convert.ToInt32(numberOfPagesRequired);
 }
 return pagingInfo;
 }
 }

ASPX Page

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="LijosTest.aspx.cs" Inherits="PagingTestWebApplication.LijosTest" %>
<%@ Register TagPrefix="CP" TagName="LijosPager" Src="~/PagingUserControl.ascx" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml">
 <head runat="server">
 <title></title>
 <style type="text/css">
 .page-numbers
 {
 border: 1px solid #CCC;
 color: #808185;
 display: block;
 float: left;
 font-size: 9pt;
 margin-right: 3px;
 padding: 4px 4px 3px;
 text-decoration: none;
 }
 
 .page-numbers.current
 {
 background-color: #808185;
 border: 1px solid #808185;
 color: white;
 font-weight: bold;
 }
 
 .page-numbers.next, .page-numbers.prev
 {
 border: 1px solid white;
 font-size: 12pt;
 }
 </style>
 </head>
 <body>
 <form id="form1" runat="server">
 <asp:TextBox ID="txtEmpName" runat="server"></asp:TextBox>
 <asp:Button ID="btnSearch" runat="server" Text="Button" ValidationGroup="Search"
 OnClick="btnSearch_Click" />
 <div>
 <asp:GridView ID="grdEmployee" runat="server">
 </asp:GridView>
 </div>
 <CP:LijosPager ID="uclPager" runat="server" />
 <asp:HiddenField ID="hdnCurrentIndex" runat="server" Value="Blank Value" />
 </form>
 </body>
 </html>

ASPX Code Behind

public partial class LijosTest : System.Web.UI.Page
{
 private int pageSize = 25;
 private int pageIndex = 1;
 protected void Page_Load(object sender, EventArgs e)
 {
 //Register event handler for user control event
 this.uclPager.PaginationLinkClicked += new EventHandler(paginationLink_Click);
 if (Page.IsPostBack)
 {
 //During all postbacks - Add the pagination links to the page
 int tableDataCount = DatabaseSimulator.GetEmployeesCount(txtEmpName.Text);
 string defaultInitialValueForHiddenControl = "Blank Value";
 int indexFromPreviousDataRetrieval = 1;
 if (!String.Equals(hdnCurrentIndex.Value, defaultInitialValueForHiddenControl))
 {
 indexFromPreviousDataRetrieval = Convert.ToInt32(hdnCurrentIndex.Value, CultureInfo.InvariantCulture);
 }
 
 //Set property of user control
 uclPager.PreviousIndex = indexFromPreviousDataRetrieval;
 //Call method in user control
 uclPager.PreAddAllLinks(tableDataCount, pageSize, indexFromPreviousDataRetrieval);
 }
 
 }
 protected void btnSearch_Click(object sender, EventArgs e)
 {
 //When Search is clicked, reset the index to 1 (first page)
 pageIndex = 1;
 BindBusinessProcessActivitiesData();
 }
 protected void paginationLink_Click(object sender, EventArgs e)
 {
 //When link is clicked, set the pageIndex from user control property
 pageIndex = uclPager.CurrentClickedIndex;
 BindBusinessProcessActivitiesData();
 }
 private void BindBusinessProcessActivitiesData()
 {
 string name = txtEmpName.Text; 
 List<Employee> searchResult = DatabaseSimulator.GetData(name, pageSize, pageIndex).ToList();
 grdEmployee.DataSource = searchResult;
 grdEmployee.DataBind();
 //Index
 hdnCurrentIndex.Value = pageIndex.ToString(CultureInfo.InvariantCulture);
 //Get total number of records
 int tableDataCount = DatabaseSimulator.GetEmployeesCount(name);
 uclPager.AddPageLinks(tableDataCount, pageSize, pageIndex);
 }
 
}

Database Part

public static class DatabaseSimulator
{
 public static IEnumerable<Employee> GetData(string name, int pageSize,int index)
 {
 IEnumerable<Employee> employeesSource = SearchEmployees(name);
 int skipUpto = ((index-1) * pageSize);
 IEnumerable<Employee> searchResult = employeesSource.Skip(skipUpto).Take(pageSize);
 return searchResult;
 }
 public static int GetEmployeesCount(string name)
 {
 List<Employee> employees = GetEmployees();
 int employeesCount = 0;
 if (String.IsNullOrEmpty(name))
 {
 employeesCount = employees.Count;
 }
 else
 {
 List<Employee> selectedEmployees = employees.Where(r => r.Name == name).ToList();
 employeesCount = selectedEmployees.Count;
 }
 return employeesCount;
 }
 private static IEnumerable<Employee> SearchEmployees(string name)
 {
 List<Employee> employees = GetEmployees();
 if (String.IsNullOrEmpty(name))
 {
 return employees;
 }
 return employees.Where(r => r.Name == name);
 }
 private static List<Employee> GetEmployees()
 {
 List<Employee> employees = new List<Employee>();
 
 for (int i = 1; i <= 400; i++)
 {
 Employee emp = new Employee();
 emp.EmpID = i;
 if (i % 2 == 0)
 {
 emp.Name = "Divisible by 2";
 }
 else if (i % 3 == 0)
 {
 emp.Name = "Divisible by 3";
 }
 else if (i % 5 == 0)
 {
 emp.Name = "Divisible by 5";
 }
 else if (i % 7 == 0)
 {
 emp.Name = "Divisible by 7";
 }
 else 
 {
 emp.Name = "Other -- "+ i.ToString();
 }
 employees.Add(emp);
 }
 return employees;
 }
}
public class Employee
{
 public int EmpID { get; set; }
 public string Name { get; set; }
}
LCJ
  • 333
  • 4
  • 15
default

AltStyle によって変換されたページ (->オリジナル) /