Reputation: 8255
I've struggled with this for quite some time. Today I finally wrote the following code.
The ViewModel contains an int
property which later tells the view how many pages the data has been split into.
The controller splits the data by taking a specified amount of rows and, in the event of paging, splits by pageNumber * recordsPerPage
Take a look:
The ViewModel
public class ThreadPostsViewModel
{
public Thread Thread { get; set; }
public List<Post> Posts { get; set; }
public int Pages { get; set; }
}
The Controller
private int PostsPerPage = 10;
public ActionResult Thread(int id, int page = 1)
{
using (OrtundEntities Db = new OrtundEntities())
{
// get the thread and its parent data (parent for breadcrumbs)
var Thread = Db.Threads.Include(t => t.Title).FirstOrDefault(x => x.Id == id);
// create a list for the Posts
List<Post> Posts = new List<Post>();
// select based on paging
if (page == 1)
// no paging has happened, get the first set of records
Posts = Db.Posts.Include(x => x.User).Where(x => x.ThreadId == id).OrderByDescending(x => x.Date).Take(PostsPerPage).ToList();
else
// we're on a new page. Skip however many rows we've already seen
Posts = Db.Posts.Include(x => x.User).Where( x=> x.ThreadId == id).OrderByDescending(x => x.Date).Take(PostsPerPage).Skip(PostsPerPage * page).ToList();
// create and return the view model
ThreadPostsViewModel Model = new ThreadPostsViewModel
{
Thread = Thread,
Posts = Posts,
Pages = Posts.Count / PostsPerPage
};
return View(Model);
}
}
The View
@model Ortund.Models.ThreadPostsViewModel
<div class="paging">
@for (int i = 1; i < Model.Pages; i++)
{
string Url = String.Format("/View/Thread/{0}?page={1}", Model.Thread.Id, i);
<a href="@Url">@i</a>
}
</div>
<div class="posts-list">
@foreach (var Post in Model.Posts)
{
<div class="post" id="@Post.Id">
</div>
}
</div>
In this code, assuming 300 posts are selected from the database and 10 posts are specified per page, then there should be 30 pages.
Even that's a hefty amount of links to fit into your page design so how can I minimize these paging links and display, say, 10 paging links only where, when you get to say, page 8, the links will change to show you 3-13, for example?
Even having the paging links display as follows would be preferable:
1 2 3 4 5 ... 90 91 92 93 94
Upvotes: 0
Views: 418
Reputation: 390
In controller put value of current page:
ViewBag.currentPage = page;
In view you can do something like this (not tested):
<div class="paging">
@if (Model.Pages > 11 && ViewBag.currentPage > 6)
{
for (int i = ViewBag.currentPage - 6; i < ViewBag.currentPage -1; i++)
{
string Url = String.Format("/View/Thread/{0}?page={1}", Model.Thread.Id, i);
<a href="@Url">@i</a>
}
for (int i = ViewBag.currentPage + 1; i < ViewBag.currentPage + 6; i++)
{
string Url = String.Format("/View/Thread/{0}?page={1}", Model.Thread.Id, i);
<a href="@Url">@i</a>
}
}
else
{
for (int i = 1; i < Model.Pages; i++)
{
string Url = String.Format("/View/Thread/{0}?page={1}", Model.Thread.Id, i);
<a href="@Url">@i</a>
}
}
</div>
Upvotes: 1