Skip to content

Instantly share code, notes, and snippets.

@pwelter34
Created November 3, 2020 22:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pwelter34/e2909bc72f9d7dae65af1d42709eb1cc to your computer and use it in GitHub Desktop.
Save pwelter34/e2909bc72f9d7dae65af1d42709eb1cc to your computer and use it in GitHub Desktop.
/// <summary>
/// A paged collection.
/// </summary>
/// <typeparam name="T">The type of the items in the list.</typeparam>
/// <remarks>
/// When this collection is created, <see cref="IQueryable"/> Skip and Take is
/// calculated and called on the source list. Also, if total count
/// is not specified, <see cref="IQueryable"/> Count is called.
/// </remarks>
public class PagedList<T> : List<T>
{
private IQueryable<T> _originalSource;
/// <summary>
/// Initializes a new instance of the <see cref="T:Novus.Common.Collections.PagedList`1"/> class.
/// </summary>
/// <param name="source">The source list of items.</param>
/// <param name="pageIndex">The zero based index of the page.</param>
/// <param name="pageSize">Size of the page.</param>
public PagedList(IEnumerable<T> source, int pageIndex, int pageSize)
: this(source, pageIndex, pageSize, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="T:Novus.Common.Collections.PagedList`1"/> class.
/// </summary>
/// <param name="source">The source list of items.</param>
/// <param name="pageIndex">The zero based index of the page.</param>
/// <param name="pageSize">Size of the page.</param>
/// <param name="totalCount">The total count.</param>
public PagedList(IEnumerable<T> source, int pageIndex, int pageSize, int? totalCount)
{
Initialize(source.AsQueryable(), pageIndex, pageSize, totalCount);
}
/// <summary>
/// Initializes a new instance of the <see cref="T:Novus.Common.Collections.PagedList`1"/> class.
/// </summary>
/// <param name="source">The source list of items.</param>
/// <param name="pageIndex">The zero based index of the page.</param>
/// <param name="pageSize">Size of the page.</param>
public PagedList(IQueryable<T> source, int pageIndex, int pageSize)
: this(source, pageIndex, pageSize, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="T:Novus.Common.Collections.PagedList`1"/> class.
/// </summary>
/// <param name="source">The source list of items.</param>
/// <param name="pageIndex">The zero based index of the page.</param>
/// <param name="pageSize">Size of the page.</param>
/// <param name="totalCount">The total count.</param>
public PagedList(IQueryable<T> source, int pageIndex, int pageSize, int? totalCount)
{
Initialize(source, pageIndex, pageSize, totalCount);
}
#region IPagedList Members
/// <summary>
/// Gets a value indicating whether this instance has previous page.
/// </summary>
/// <value>
/// <c>true</c> if this instance has previous page; otherwise, <c>false</c>.
/// </value>
public bool HasPreviousPage => (PageIndex > 0);
/// <summary>
/// Gets a value indicating whether this instance has next page.
/// </summary>
/// <value>
/// <c>true</c> if this instance has next page; otherwise, <c>false</c>.
/// </value>
public bool HasNextPage => (PageIndex < (PageCount - 1));
/// <summary>
/// Gets a value indicating whether this instance is first page.
/// </summary>
/// <value>
/// <c>true</c> if this instance is first page; otherwise, <c>false</c>.
/// </value>
public bool IsFirstPage => (PageIndex <= 0);
/// <summary>
/// Gets a value indicating whether this instance is last page.
/// </summary>
/// <value>
/// <c>true</c> if this instance is last page; otherwise, <c>false</c>.
/// </value>
public bool IsLastPage => (PageIndex >= (PageCount - 1));
/// <summary>
/// Gets the total page count.
/// </summary>
/// <value>The total page count.</value>
public int PageCount => TotalItemCount > 0 ? (int)Math.Ceiling(TotalItemCount / (double)PageSize) : 0;
/// <summary>
/// Gets the zero based index of the page.
/// </summary>
/// <value>The index of the page.</value>
public int PageIndex { get; private set; }
/// <summary>
/// Gets the page number. Page number is PageIndex + 1.
/// </summary>
/// <value>The page number.</value>
public int PageNumber { get { return PageIndex + 1; } }
/// <summary>
/// Gets the size of the page.
/// </summary>
/// <value>The size of the page.</value>
public int PageSize { get; private set; }
/// <summary>
/// Gets the total item count.
/// </summary>
/// <value>The total item count.</value>
public int TotalItemCount { get; private set; }
#endregion
/// <summary>
/// Initializes the specified source.
/// </summary>
/// <param name="source">The source list of items.</param>
/// <param name="pageIndex">The zero based index of the page.</param>
/// <param name="pageSize">Size of the page.</param>
/// <param name="totalCount">The total item count.</param>
protected void Initialize(IQueryable<T> source, int pageIndex, int pageSize, int? totalCount)
{
if (pageIndex < 0)
throw new ArgumentOutOfRangeException("pageIndex", "PageIndex cannot be below 0.");
if (pageSize < 1)
throw new ArgumentOutOfRangeException("pageSize", "PageSize cannot be less than 1.");
if (source == null)
source = new List<T>().AsQueryable();
_originalSource = source;
PageSize = pageSize;
PageIndex = pageIndex;
int skip = (pageIndex) * pageSize;
if (totalCount.HasValue)
{
TotalItemCount = totalCount.Value;
AddPage(source, skip, pageSize);
return;
}
// runs 2 queries
TotalItemCount = source.Count();
AddPage(source, skip, pageSize);
}
private void AddPage(IQueryable<T> source, int skip, int pageSize)
{
if (TotalItemCount == 0)
return;
IQueryable<T> page = (source).Skip(skip).Take(pageSize);
AddRange(page.ToList());
}
/// <summary>
/// Gets the next page of data using the original source.
/// </summary>
/// <returns>
/// A new PageList with the current page index incremented.
/// </returns>
/// <remarks>
/// The source, page size and total will be the same as the current PageList.
/// </remarks>
public PagedList<T> NextPage()
{
if (_originalSource == null || !HasNextPage)
return null;
return new PagedList<T>(_originalSource, PageIndex + 1, PageSize, TotalItemCount);
}
/// <summary>
/// Gets the previous page of data using the original source.
/// </summary>
/// <returns>
/// A new PageList with the current page index decremented.
/// </returns>
/// <remarks>
/// The source, page size and total will be the same as the current PageList.
/// </remarks>
public PagedList<T> PreviousPage()
{
if (_originalSource == null || !HasPreviousPage)
return null;
return new PagedList<T>(_originalSource, PageIndex - 1, PageSize, TotalItemCount);
}
/// <summary>
/// Gets the paged list of data from the specified page index.
/// </summary>
/// <param name="pageIndex">The zero based index of the page.</param>
/// <returns>
/// A new PageList with data from the specified page index.
/// </returns>
/// <remarks>
/// The source, page size and total will be the same as the current PageList.
/// </remarks>
public PagedList<T> GotoPage(int pageIndex)
{
if (_originalSource == null)
return null;
return new PagedList<T>(_originalSource, pageIndex, PageSize, TotalItemCount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment