Вопрос

I'm not using a Grid, just using the MvcContrib Pager. I have a partial view created for the Pager (so I can display it at top and bottom of the results easily), and it calls the @Html. Pager method as so:

 @Html.Pager(Model.PagedPrograms).First("<<").Last(">>").Next(">").Previous("<").Format("Item {0} - {1} of {2} ")

This works without additional tweaking as long as all parameters are passed to the page via QueryString, since Pager knows to rebuild those back on the URLs.

I'd like to give the user the option to change the page size (say 20, 50, All) ... I can easily handle that on the controller end, and I could write something like

@if (Model is Foo) {
     @Html.ActionLink<SearchController>(sc => sc.Foo(var1, var2, var3, 20), "20")
     @Html.ActionLink<SearchController>(sc => sc.Foo(var1, var2, var3, 50), "50");
     @Html.ActionLink<SearchController>(sc => sc.Foo(var1, var2, var3, -1), "All");
}

But I would have to do that for each Model type that might use this Pager... I might be overthinking this or coming at this completely backwards, but I thought I'd ask and see if anyone had insight.

Currently the Pager is only called from a view which takes IPagedProgramList (provides IPagination<ProgramDTO> { get; }), and I have two ViewModels implementing that interface (a simple search and an advanced search). But if this project grows and we add new ViewModels that use that Interface I would have to update the Pager partial view, and that seems bad / doesn't scale / etc.

Это было полезно?

Решение

So a nod to Ek0nomik who got me thinking outside the box on this one.

Step 1: Make sure all pages that are going to use the Pager controller are passing all parameters via GET not POST. Use RedirectToAction if you must accept post somewhere and just translate all the parameters into primitive types for the GET method.

Step 2: Don't worry about adding .Link() to the Pager. As long as everything's coming in via GET, you're fine. It will look at the URL for the page and adjust the page number parameter as it needs to when you're going forward/back.

Step 3 (optional but recommended): For consistency across your application, somewhere (probably your Global.ascx.cs file) you should define a list of the page sizes you will support. In my case I used Dictionary<int,string> so that I could pass -1 as the PageSize value but display All (and of course the data layer must know that -1 means disable paging).

Step 4: Add something like this to your pager partial view:

<ul class="pageSizeSelector">
        @foreach (KeyValuePair<int,string> kvp in MvcApplication.AVAIL_PAGE_SIZES)
        {
            <li><a href="#" onclick="changePageSize(@kvp.Key)">@kvp.Value</a></li>
        }
 </ul>

Step 5: The javascript function changePageSize is so simple, I couldn't believe I hadn't thought of this first (note: no jQuery required... just in case you're not already using it, you don't need to just for this).

function changePageSize(size) {
  var PSpattern = /PageSize=\d+/i;
  var url = window.location.href;
  url = url.replace(PSpattern, "PageSize=" + size);
  window.location.href = url;
}

Step 6 (optional, unless you're an Internet Troll): Profit!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top