How to create a page navigation partial view? - c#

I have a PaginatedList<T> class inheriting from List<T> in an ASP.NET Core app that my controllers and views use to render paginated content:
public class PaginatedList<T> : List<T>
{
public int PageNumber { get; private set; } = 1; // page index
public int PageSize { get; private set; } = 25; // item count in each page
public int TotalCount { get; private set; } // total items in all pages
public int PageCount { get; private set; } // total page count
public bool HasPreviousPage => PageNumber > 1;
public bool HasNextPage => PageNumber < PageCount;
public int From => PageSize * (PageNumber - 1) + 1; // index of first item in page
public int To => From + Count - 1; // index of last item in page
//Method bodies omitted for brevity
public static async Task<PaginatedList<T>> CreateAsync(
IQueryable<T> source, int pageSize = 25, int pageNumber = 1) {..}
private PaginatedList(
List<T> items, int count, int pageSize = 25, int pageNumber = 1) {..}
}
Code based on this with additional validation.
I have noticed that almost all of my views serving paginated lists have the same page navigation UI. (For all entities in the app like Person, Book, etc.):
#model PaginatedList<Person>
#*View-specific code here...*#
<nav aria-label="Page Navigation">
#if (Model.Count > 1)
{
#* Display the range of entities displayed *#
<div class="text-center text-muted my-2">
<em>Showing #Model.From to #Model.To out of #Model.TotalCount</em>
</div>
}
<ul class="pagination justify-content-center">
#if (Model.HasPreviousPage || Model.HasNextPage)
{
#if (Model.HasPreviousPage)
{
<li class="page-item">
<a asp-controller="Person"
asp-action="Index"
asp-route-repoId="#Model.RepoId"
asp-route-page="#(Model.PageNumber - 1)"
title="Previous" class="page-link" aria-label="Previous">
<span class="sr-only">Previous</span>«
</a>
</li>
}
else
{
<li class="page-item disabled">
<a class="page-link" tabindex="-1">
<span class="sr-only">Previous</span>«
</a>
</li>
}
<li class="page-item active" aria-current="page">
<a class="page-link" href="#">#Model.PageNumber</a>
</li>
#if (Model.HasNextPage)
{
<li class="page-item">
<a
asp-controller="Person"
asp-action="Index"
asp-route-repoId="#Model.RepoId"
asp-route-page="#(Model.PageNumber + 1)" title="Next" class="page-link" aria-label="Next">
<span class="sr-only">Next</span>»
</a>
</li>
}
else
{
<li class="page-item disabled">
<a class="page-link" tabindex="-1">
<span class="sr-only">Next</span>»
</a>
</li>
}
}
</ul>
</nav>
I would like to extract this to a partial view called _PageNav.cshtml. But there are two things I'm not quite sure about:
The PaginatedList<T> class is generic and I cannot have a partial view with a model called PaginatedList<T> with an open generic parameter T. One possible solution I can think of is writing a non-generic interface called IPaginatedList that has all the properties required for page navigation and then have PaginatedList<T> implement it. This is because the navigation UI does not need to know anything about the items in the list. Then I can use IPaginatedList as the model for my partial view:
public interface IPaginatedList
{
public int PageNumber { get; }
public int PageSize { get; }
public int TotalCount { get; }
public int PageCount { get; }
public bool HasPreviousPage { get; }
public bool HasNextPage { get; }
public int From { get; }
public int To { get; }
}
public class PaginatedList<T> : List<T>, IPaginatedList
{
...
}
_PageNav.cshtml:
#model IPaginatedList
#* Navigation UI *#
...
This would kind of solve the first issue.
The second issue is that each view with a paginated list has a different previous and next page link. (the area/controller/action name for the link and different route values):
#* Previous page link *#
<a asp-controller="Persons"
asp-action="Index"
asp-route-repoId="#Model.RepoId"
asp-route-page="#(Model.PageNumber - 1)"
title="Previous"
class="page-link"
aria-label="Previous">
<span class="sr-only">Previous</span>«
</a>
#* Next page link *#
<a asp-controller="Persons"
asp-action="Index"
asp-route-repoId="#Model.RepoId"
asp-route-page="#(Model.PageNumber + 1)"
title="Next"
class="page-link"
aria-label="Next">
<span class="sr-only">Next</span>»
</a>
The above would be the previous and next links for the Index action of PersonsController (Person entity). This would change for another entity like Book.
Should I have a property for each link tag helper argument in my PaginatedList<T> like ControllerName, ActionName, etc.? Is there a better way?
Can this be solved with a custom tag-helper? What am I missing?

I have solution for using tag helpers
public class PaginationTagHelper : TagHelper
{
[HtmlAttributeName("onclick-method-name")]
public string OnClick { get; set; }
[HtmlAttributeName("current-page-index")]
public int CurrentPage { get; set; }
[HtmlAttributeName("end-page")]
public int EndPage { get; set; }
[HtmlAttributeName("start-page")]
public int StartPage { get; set; }
[HtmlAttributeName("total-page-count")]
public int TotalPages { get; set; }
/// <summary>
/// Process
/// </summary>
/// <param name="context"></param>
/// <param name="output"></param>
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var onclickMethodFormat = OnClick + "({0})"; // 0 - pagenumber .
var onclickMethod = string.Empty;
StringBuilder content = new StringBuilder();
content.Append("<nav aria-label=\"Page navigation example\" class=\"pagin-holder clearfix\"> <ul class=\"pagination pagination-sm\">");
if (EndPage > 1)
{
if (CurrentPage > 1)
{
onclickMethod = string.Format(onclickMethodFormat, CurrentPage - 1);
content.Append("<li class=\"page-item\"> Previous</li>");
}
for (var page = StartPage; page <= EndPage; page++)
{
onclickMethod = string.Format(onclickMethodFormat, page);
if (page == CurrentPage)
{
content.Append("<li class=\"page-item active\">").Append(page).Append(" ");
}
else
{
content.Append("<li class=\"page-item\">").Append(page).Append(" ");
}
}
if (CurrentPage < TotalPages)
{
onclickMethod = string.Format(onclickMethodFormat, CurrentPage + 1);
content.Append("<li class=\"page-item\"> Next </li>");
}
}
output.Content.AppendHtml(content.ToString());
}
}
This is my custom pagination class
public class PagingInfo
{
public int PageIndex { get; set; }
public int PageSize { get; set; }
public string SortOrder { get; set; }
public byte SortColumn { get; set; }
public string SortColumnName { get; set; }
public int TotalRecords { get; set; }
public string SearchText { get; set; }
public byte FilterByColumn { get; set; }
public string FilterByColumnName { get; set; }
}
public class Pager
{
public Pager(long totalItems, int? page, int pageSize = 10)
{
// calculate total, start and end pages
var totalPages = (int)Math.Ceiling((decimal)totalItems / (decimal)pageSize);
var currentPage = page != null ? (int)page : 1;
var startPage = currentPage - 5;
var endPage = currentPage + 4;
if (startPage <= 0)
{
endPage -= (startPage - 1);
startPage = 1;
}
if (endPage > totalPages)
{
endPage = totalPages;
if (endPage > 10)
{
startPage = endPage - 9;
}
}
TotalItems = totalItems;
CurrentPage = currentPage;
PageSize = pageSize;
TotalPages = totalPages;
StartPage = startPage;
EndPage = endPage;
}
public long TotalItems { get; set; }
public int CurrentPage { get; set; }
public int PageSize { get; set; }
public int TotalPages { get; set; }
public int StartPage { get; set; }
public int EndPage { get; set; }
}
Added tag helper in view:
<Pagination onclick-method-name="Index" current-page-index="Model.PagingInfo.CurrentPage" end-page="Model.PagingInfo.EndPage"
start-page="Model.PagingInfo.StartPage" total-page-count="Model.PagingInfo.TotalPages"></Pagination>

Related

how can i solve 'Object reference not set to an instance of an object.' in blazor?

I giv up to solve this. i dont't know what is wrong with my code, if the problem is instance of object, i tried to give my pagging class an instance but still no clue.
This is my index class;
<DataGridComponent TItem="Employee"
DataItems="listEmployee"
Columns="columnDefinitions"
Paging="#(new PagingConfig {
Enabled = true,
CustomPager = true,
PageSize = 3
})">
<CustomPager>
<button class="btn btn-primary" #onclick="PrevPage"> Prev </button>
<span> Page
<input type="number" min="1"#bind-value="#DataGrid.currentPageNumber"/>
of #DataGrid.MaxPageNumber </span>
<button class="btn btn-primary" #onclick="NextPage"> Next </button>
</CustomPager>
</DataGridComponent>
#code{
private DataGridComponent<Employee> DataGrid;
private List<Employee> listEmployee;
private List<ColumnDefinition> columnDefinitions;
protected override void OnInitialized()
{
base.OnInitialized();
Initialize();
}
private void PrevPage()
{
DataGrid.GoToPrevPage();
}
private void NextPage()
{
DataGrid.GoToNextPage();
}
this is my DataGrid class
<div class="level">
<div class="level-left"></div>
<div class="level-right">
<div class="level-item">
#if (Paging != null && Paging.Enabled)
{
#if (Paging.CustomPager)
{
#CustomPager
}
else
{
<span #onclick="GoToPrevPage"><b><</b>Prev</span>
<span> #currentPageNumber of #Paging.MaxPageNumber(DataItems.Count)
</span>
<span #onclick="GoToNextPage"><b>Next></b></span>
}
}
</div>
</div>
</div>
#code {
[Parameter]
public int currentPageNumber { get; set; } = 1;
[Parameter]
public List<TItem> DataItems { get; set; }
[Parameter]
public List<ColumnDefinition> Columns { get; set; }
[Parameter]
public PagingConfig Paging { get; set; } = new PagingConfig();
[Parameter]
public RenderFragment CustomPager { get; set; }
public void GoToPrevPage()
{
currentPageNumber = Paging.PrevPageNumber(currentPageNumber);
}
public void GoToNextPage()
{
currentPageNumber = Paging.NextPageNumber(currentPageNumber, DataItems.Count);
}
public int MaxPageNumber { get => Paging.MaxPageNumber(DataItems.Count); }
}
and this is my my pagingconfig
public class PagingConfig
{
public bool Enabled { get; set; }
public int PageSize { get; set; }
public bool CustomPager { get; set; }
public int NumOfItemsToSkip(int pageNumber)
{
if (Enabled)
{
return (pageNumber - 1) * PageSize;
}
else
return 0;
}
public int NumOfItemsToTake(int totalItemCount)
{
if (Enabled)
{
return PageSize;
}
return totalItemCount;
}
public int PrevPageNumber(int currentPageNumber)
{
if (currentPageNumber > 1)
return currentPageNumber - 1;
else
return 1;
}
public int NextPageNumber(int currentPageNumber, int totalItemsCount)
{
if (currentPageNumber < MaxPageNumber(totalItemsCount))
{
return currentPageNumber + 1;
}
else
{
return currentPageNumber;
}
}
public int MaxPageNumber(int totalItemcount)
{
int maxPageNumber;
double numberOfPage = (double)totalItemcount / (double)PageSize;
if (numberOfPage == Math.Floor(numberOfPage))
{
maxPageNumber = (int)numberOfPage;
}
else
{
maxPageNumber = (int)numberOfPage + 1;
}
return maxPageNumber;
}
}
}
the problem is, when i tried to set enabled into true, the pagging config should get the value of true from index. But it's said not set the instance object yet. i tried to put in, the new Pagging instance into grid component but still no clue :(
DataGrid needs to be assigned. I think you want this:
<DataGridComponent #ref="DataGrid" TItem="Employee" ...>
...
</DataGridComponent>
the reference is to the variable in this line:
private DataGridComponent<Employee> DataGrid;
It's just the #ref="DataGrid" missing in the markup of your DataGridComponent. Therefore, your private DataGrid variable is null.
In Index.razor you set up a DataGridComponent instance in Razor and then declare another one in the code section private DataGridComponent<Employee> DataGrid. These are two unlinked instances of DataGridComponent. To reference DataGrid to your razor declared version you need to use #ref as below.
<DataGridComponent TItem="Employee"
DataItems="listEmployee"
Columns="columnDefinitions"
#ref = "this.DataGrid"
Paging="#(new PagingConfig {
Enabled = true,
CustomPager = true,
PageSize = 3
})">

ASP.NET Core Paging help needed

Needed help . So I am currently working on ASP.NET Core Paging and it's not working properly.it shows me the same result in the pages. I don't know where is the problem :/ Does anyone know how to solve this problem ,here is my code
Controlor
public IActionResult Index( int? pageNumber)
{
int pageSize = 5;
var personnels = from s in _context.personnels
select s;
return View(Pagination<PersonnelModel>.CreateAsync(personnels.AsQueryable<PersonnelModel>(), pageNumber ?? 1, pageSize));
}
Pagination Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
namespace personnelAUTHENTIFICATION
{
public class Pagination<T> : List<T>
{
public int PageIndex { get; private set; }
public int TotalPages { get; private set; }
public Pagination(List<T> items, int count, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);
this.AddRange(items);
}
public bool HasPreviousPage
{
get
{
return (PageIndex > 1);
}
}
public bool HasNextPage
{
get
{
return (PageIndex < TotalPages);
}
}
public int TotalPageNo
{
get
{
return TotalPages;
}
}
public static Pagination<T> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize)
{
var count = source.Count();
var items = source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
return new Pagination<T>(items, count, pageIndex, pageSize);
}
}
}
I have tested your code in my sample, it seems that everything works well on my side. I think perhaps the issue is related to the Page links in the View page. Please check whether the link url and page number are correct.
You could also refer the following sample code:
Code in the controller:
public IActionResult EmployeeIndex(int? pageNumber, int? CurrentPage)
{
int pageSize = 3;
if(CurrentPage != null)
{
pageNumber = CurrentPage;
ViewBag.CurrentPage = CurrentPage;
}
return View(Pagination<Employee>.CreateAsync(GetEmployee().AsQueryable<Employee>(), pageNumber ?? 1, pageSize));
}
Code in the View page:
#model Pagination<MVCSample.Models.Employee>
<table class="table">
...table content...
</table>
#{
var prevDisabled = !Model.HasPreviousPage ? "disabled" : "";
var nextDisabled = !Model.HasNextPage ? "disabled" : "";
}
<ul class="pagination">
<li>
<a asp-action="EmployeeIndex"
asp-route-pageNumber="#(Model.PageIndex - 1)"
class="btn btn-default #prevDisabled">
Previous
</a>
</li>c
#for (var i = 1; i <= Model.TotalPages; i++)
{
<li class="page-item #(i == ViewBag.CurrentPage ? "active" : "")">
<a asp-action="EmployeeIndex" asp-route-currentpage="#i" class="page-link">#i</a>
</li>
}
<li>
<a asp-action="EmployeeIndex"
asp-route-pageNumber="#(Model.PageIndex + 1)"
class="btn btn-default #nextDisabled">
Next
</a>
</li>
</ul>
Please check the action method, you could change it to your owns.
Code in the Pagination.cs (based on your code, I just add a CurrentPage property to display the current page number):
public class Pagination<T>:List<T>
{
[BindProperty(SupportsGet = true)]
public int CurrentPage { get; set; } = 1
....
}
The result like this:

TextboxFor in MVC is not binding to Model inside a for loop

My Viewmodel (contains a number of submodels) is:
public class ViewModel
{
public IEnumerable<tblQuestion> DemoQuestions { get; set; }
public IEnumerable<tblQuestion> TechQuestions { get; set; }
public List<tblAnswer> DemoQ1Answers { get; set; }
public List<tblAnswer> DemoQ2Answers { get; set; }
public List<tblAnswer> TechAnswers { get; set; }
public string selectedAnswerIDforQ1 { get; set; }
public string selectedAnswerIDforQ2 { get; set; }
}
My tblAnswer model is like below:
public partial class tblAnswer
{
public int AnswerID { get; set; }
public Nullable<int> QuestionID { get; set; }
public string AnswerDescription { get; set; }
public string Q1Other { get; set; }
}
This is my view code:
#using (Html.BeginForm("Display", "Questionnaire", FormMethod.Post))
{
foreach (tblQuestion question in Model.DemoQuestions)
{
<p>#question.QuestionDescription</p>
#for (int i = 0; i < Model.DemoQ1Answers.Count(); i++)
{
if (question.QuestionID == 1)
{
<div class="col-md-4">
#Html.RadioButtonFor(m => Model.selectedAnswerIDforQ1, Model.DemoQ1Answers[i].AnswerID)
#Model.DemoQ1Answers[i].AnswerDescription
#Html.HiddenFor(m => Model.DemoQ1Answers[i].AnswerID)
#Html.HiddenFor(m => Model.DemoQ1Answers[i].AnswerDescription)
#if (Model.DemoQ1Answers[i].AnswerID == 4)
{
#Html.TextBoxFor(m => Model.DemoQ1Answers[i].Q1Other)
}
</div>
}
}
}
<input type="submit" value="Submit" />
}
When I press submit, my textbox value in the model is null. Means, mymodel.DemoQ1Answers[3].Q1Other is null. All other model values are bound with model values in the view except this one.
This is my controller:
[HttpPost]
public ActionResult Display(ViewModel mymodel)
{
foreach (var demoqstns in mymodel.DemoQuestions)
{
int AnswerSelected = 0;
string otherText = null;
if (qstnID == 1)
{
AnswerSelected = Convert.ToInt32(mymodel.selectedAnswerIDforQ1);
if (AnswerSelected == 4)
{
otherText = mymodel.DemoQ1Answers[3].Q1Other;
}
}
else if (qstnID == 2)
{
AnswerSelected = Convert.ToInt32(mymodel.selectedAnswerIDforQ2);
}
}
}
Please help.
you have to use for loop instated of foreach
for (var i = 0; i < Model.Orders.Count(); i++)
#Html.HiddenFor(x => Model.Orders[i].CustomerID)
the index value i appears in the lambda expression for each form element being generated by the loop, The TextBoxFor HtmlHelper is used, rather than the more general (and automagic) DisplayFor and EditorFor.

How can I modify this to have a Google-like paging?

My controller class contains
var Paged = new PaginatedList<Products>(SideBar, page ?? 0, pageSize);
if (Request.IsAjaxRequest())
{
return PartialView("~/Views/Shared/_Grid.cshtml", Paged);
}
return View(Paged);
the PaginatedList is
public class PaginatedList<T> : List<T>
{
public int PageIndex { get; private set; }
public int PageSize { get; private set; }
public int TotalCount { get; private set; }
public int TotalPages { get; private set; }
public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
PageSize = pageSize;
TotalCount = source.Count();
TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize));
}
public bool HasPreviousPage
{
get
{
return (PageIndex > 0);
}
}
public bool HasNextPage
{
get
{
return (PageIndex + 1 < TotalPages);
}
}
}
And my view is
<div class="pagination-container">
<nav class="pagination">
<ul>
#for (int i = 0; i < Model.TotalPages; i++)
{
<li><a href="#Url.Action("Index", "Home", new { page = i})"
class="#(i == Model.PageIndex ? "current-page" : "")">#(i + 1)</a></li>
}
</ul>
</nav>
<nav class="pagination-next-prev">
<ul>
#if (Model.HasPreviousPage) {
<li></li>
}
#if (Model.HasNextPage) {
<li></li>
}
</ul>
</nav>
<div>
Page #(Model.PageIndex + 1) of #Model.TotalPages
</div>
</div>
One problem with the view above, is that it creates numeric pages equal to the page sizes within model. If the model has 6 pages the result is
What will happen if i have 100 Model.Pages ?
You need to make sure that you separate you're not returning all the data in the model - you return only return the page size, at most, and have a separate property to store the total count.
For instance:
public class PageResult<T> where T : class
{
public PageResult(IEnumerable<T> items, int page = 1, int pageSize = 10)
{
this.Items = items;
this.PageSize = pageSize;
this.PageIndex = page;
this.PaginateData(page);
}
public IEnumerable<T> Items { get; private set; }
public int PageSize { get; private set; }
public int PageIndex { get; private set; }
public int Total { get; private set; }
public int TotalPages
{
get
{
return Math.Max((int)Math.Ceiling((Total / (double)PageSize)), 1);
}
}
private int _MaxPagesToDisplay = 10;
public int MaxPagesToDisplay
{
get { return _MaxPagesToDisplay; }
set { _MaxPagesToDisplay = value; }
}
public int PagesToDisplay
{
get
{
return Math.Min(this.MaxPagesToDisplay, TotalPages);
}
}
public void PaginateData(int page)
{
if(this.Items == null) return;
this.Total = this.Items.Count();
this.Items = this.Items.Skip(this.PageSize * this.PageIndex - 1).Take(this.PageSize);
}
}
This will mean you can return for example 1 million results and set the Total to 1 million, but only insert 10 into the Items collection. You can use Linq to paginate the data into this collection. I added the method PaginateData which does it for you.
Then you can update your view:
#for (int i = 1; i <= Model.PagesToDisplay; i++)
{
<li><a href="#Url.Action("Index", "Home", new { page = i})"
class="#(i == Model.PageIndex ? "current-page" : "")">#(i)</a></li>
}
You can then use the Total field to display the total count on the page.

How to pass information from controller to viewdata? asp net mvc c#

I am building a pagination my mvc project and have follew problem.
I did everything for pagination and now need just pass a page information to view data in view.
I have a user control Pagination:
Pagination.ascx:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="Pagination.ascx.cs"
Inherits="PIMP.Web.TestForum.Views.Shared.Pagination" %>
<ul id="pagination-flickr">
<% if (ViewData.Model.HasPreviousPage)
{ %>
<li class="previous"><a href="<%=ViewData.PageActionLink.Replace("%7Bpage%7D", (ViewData.PageIndex - 1).ToString())%>">
« Previous</a></li>
<% }
else
{ %>
<li class="previous-off">« Previous</li>
<% } %>
<%for (int page = 1; page <= ViewData.Model.TotalPages; page++)
{
if (page == ViewData.Model.PageIndex)
{ %>
<li class="active">
<%=page.ToString()%></li>
<% }
else
{ %>
<li><a href="<%=ViewData.PageActionLink.Replace("%7Bpage%7D", page.ToString())%>">
<%=page.ToString()%></a></li>
<% }
}
if (ViewData.Model.HasNextPage)
{ %>
<li class="next"><a href="<%=ViewData.PageActionLink.Replace("%7Bpage%7D", (ViewData.PageIndex + 1).ToString())%>">
Next »</a></li>
<% }
else
{ %>
<li class="next-off">Next »</li>
<% } %>
</ul>
<ul id="pagination-flickr0">
<li></li>
</ul>
Pagination.ascx.cs:
public partial class PaginationViewData
{
public int PageIndex { get; set; }
public int TotalPages { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public string PageActionLink { get; set; }
public bool HasPreviousPage
{
get
{
return (PageIndex > 1);
}
}
public bool HasNextPage
{
get
{
return (PageIndex * PageSize) <= TotalCount;
}
}
}
public partial class Pagination : System.Web.Mvc.ViewUserControl<PaginationViewData>
{
public Pagination()
{
}
}
class PagedList.cs:
namespace PIMP.Web.TestForum.DataObject.Forum
{
public class PagedList<T>: List<T>
{
public PagedList(IQueryable<T> source, int index, int pageSize)
{
this.TotalCount = source.Count();
this.PageSize = pageSize;
this.PageIndex = index;
this.AddRange(source.Skip((index - 1) * pageSize).Take(pageSize).ToList());
int pageResult = 0;
for (int counter = 1; pageResult < this.TotalCount; counter++)
{
pageResult = counter * this.PageSize;
this.TotalPages = counter;
}
}
public PagedList()
{
}
public int TotalPages
{
get;
set;
}
public int TotalCount
{
get;
set;
}
public int PageIndex
{
get;
set;
}
public int PageSize
{
get;
set;
}
public bool HasPreviousPage
{
get
{
return (PageIndex > 1);
}
}
public bool HasNextPage
{
get
{
return (PageIndex * PageSize) <= TotalCount;
}
}
}
public static class Pagination
{
public static PagedList<T> ToPagedList<T>(this IQueryable<T> source, int index, int pageSize)
{
return new PagedList<T>(source, index, pageSize);
}
public static PagedList<T> ToPagedList<T>(this IQueryable<T> source, int index)
{
return new PagedList<T>(source, index, 10);
}
}
}
in View I am doing following:
<% Html.RenderPartial("Pagination", new NISE.Web.TestForum.Views.Shared.PaginationViewData()
{
PageIndex = ViewData.Model.PageIndex,
TotalPages = ViewData.Model.TotalPages,
PageActionLink = Url.Action("Forum", "Thread", new { id = this.Model.Id, page = "{page}" }),
TotalCount = ViewData.Model.TotalCount,
PageSize = ViewData.Model.PageSize
}, null);%>
I dont know what I should do in my controller.
How can I pass Page Information to the ViewData?
My controller looks like that, can you help me to extend it??
[HttpGet]
[ValidateInput(false)]
public ActionResult Thread(Guid id)
{
try
{
ThreadModel model = new ThreadModel(id);
model.IncreaseHitCount();
PagedList<ListView> list = new PagedList<ListView>();
list.PageIndex = 0;
list.PageSize = 0;
list.TotalCount = 0;
list.TotalPages = 0;
return View(model);
}
catch (Exception ex)
{
bool rethrow = ExceptionHelper.Handle(ex, "Business Logic");
if (rethrow)
{
throw;
}
}
return View();
}
Well, I did it like this:
I created a "view-model" of (my custom) data grid which contains infos about the current page, page size, etc.
it looks like this:
using System.Collections.Generic;
public class GridContent<T>
{
public IEnumerable<T> Data { get; set; }
public int PageIndex { get; set; }
public int TotalPages { get; set; }
public int TotalItems { get; set; }
}
in the controller I then return the following:
return View(new GridContent<Entity>()
{
Data = entityEnumeration, // your actual data
PageIndex = pageIndex,
TotalItems = totalItems,
TotalPages = totalItems / pageSize + 1
});
and finally on the view
<%# Page Title="SomeTitle" Language="C#" Inherits="System.Web.Mvc.ViewPage<GridContent<Entity>>" %>
Now you can access the pagination information as well as the data using the wrapper model / class GridContent.
Hope this helps.

Categories

Resources