Ortund
Ortund

Reputation: 8255

Minimizing paging links in Asp.Net MVC

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

Answers (1)

OctoCode
OctoCode

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

Related Questions