A common way to extract a page from a set of records by checking whether the index of that record is between the index of the first and last items on that page.
While not difficult to do it's easy to accidentally get wrong, if you don't crunch the numbers properly.
This PagingLocation
class allows a paging location to be set (like a set of co-ordinates) and then passed to the data access tier to tell it which page to extract.
It includes an IsInPage(int)
function which will tell you if the index you provide is within the specified page.
It also has an AbsoluteTotal
property which holds the total number of items found in all pages. This is used by the UI to calculate how many pages to let the user choose from.
Here's a crude example of how it's used:
void Page_Load(object sender, EventArgs e)
{
int pageIndex = 2;
int pageSize = 10;
PagingLocation location = new PagingLocation(pageIndex, pageSize);
ArrayList page = GetPage(location);
grid.DataSource = page;
grid.VirtualItemCount = location.AbsoluteTotal;
grid.DataBind();
}
ArrayList GetPage(PagingLocation location)
{
ArrayList list = GetAllData();
location.AbsoluteTotal = list.Count;
for (int i = 0; i < list.Count; i++)
{
if (location.IsInPage(i))
page.Add(list[i]);
}
}
Here's a real world example of it being used by a data access component:
protected virtual IEntity[] GetPage(IObjectSet objectSet, PagingLocation location)
{
int i = 0;
List<IEntity> list = new List<IEntity>();
for (i = 0; i < objectSet.Count; i++)
{
if (location.IsInPage(i))
{
list.Add((IEntity)objectSet[i]);
}
}
location.AbsoluteTotal = i;
return list.ToArray();
}
http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.Data.Db4o/Db4oDataIndexer.cs#791[^]
Here's the PagingLocation
class (with the logging code removed):
using System;
using SoftwareMonkeys.SiteStarter.Diagnostics;
namespace SoftwareMonkeys.SiteStarter.Entities
{
public class PagingLocation : IPagingLocation
{
private int pageIndex;
public int PageIndex
{
get { return pageIndex; }
set { pageIndex = value; }
}
private int pageSize;
public int PageSize
{
get { return pageSize; }
set { pageSize = value; }
}
private int absoluteTotal;
public int AbsoluteTotal
{
get { return absoluteTotal; }
set { absoluteTotal = value; }
}
public PagingLocation()
{
}
public PagingLocation(int pageIndex, int pageSize)
{
PageIndex = pageIndex;
PageSize = pageSize;
}
public bool IsInPage(int i)
{
bool isInPage = false;
int first = (pageIndex * pageSize);
int last = ((pageIndex * pageSize) + pageSize) -1;
isInPage = i >= first
&& i <= last;
return isInPage;
}
}
}
http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.Entities/PagingLocation.cs[^]
To ensure it works properly here are a bunch of unit tests: http://code.google.com/p/sitestarter/source/browse/trunk/Src/App/SoftwareMonkeys.SiteStarter.Entities.Tests/PagingLocationTests.cs[^]