Rectangle 27 5

Here is a workaround that doesn't use JavaScript.

The problem as I see it, the paging links do not receive any route information that must be preserved, like a search filter. IMO this is a blatant oversight! A little extra thought here would have saved lots of headache!

This technique "throws away" the WebGrid's built-in paging, and uses a Helper to generate the paging links, along with the precious route data we want.

Once completed, you simply render the WebGrid as the grid only, and use the Helper to make the paging links. One advantage here is you can put those at the top and bottom, which we like to do.

I attempted to use similar CSS to what is provided in the Pager.css that NuGet puts into your solution. The helper should be complete enough for some of you, but it is easily extended.

New New New I just updated the helper with an Ajax version. I am a little n00b with Razor helpers, so i couldn't figure out how to re-factor it to use a common template; anyone please? The important extra detail there is to pass in the AjaxOptions and make sure to use POST as the verb, otherwise you may not end up in the correct controller method.

@helper DoPager(System.Web.Mvc.HtmlHelper hh, string pageActionName, WebGrid grid, int maxPageLinks, object rvd) {
<div class="pager">
<div class="pageof">Page <b>@(grid.PageIndex + 1)</b> of <b>@grid.PageCount</b></div>
@if (grid.PageCount > 1) {
<ul>
<li>
@{ RouteValueDictionary rvdp1 = new RouteValueDictionary(rvd);
   rvdp1.Add("Page", 1);
}
@hh.ActionLink("<<", pageActionName, rvdp1)
</li>
@{ int start = Math.Max(0, grid.PageIndex - maxPageLinks / 2); }
@for (int ix = 0; ix + start < grid.PageCount; ix++) {
    int pageno = start + ix + 1;
    var css = hh.Raw(pageno - 1 == grid.PageIndex ? " class=\"highlighted\"" : "");
    RouteValueDictionary rvdp = new RouteValueDictionary(rvd);
    rvdp.Add("Page", pageno);
<li@css>
@hh.ActionLink(pageno.ToString(), pageActionName, rvdp)
</li>
    if (ix >= maxPageLinks) { break; }
}
<li>
@{ RouteValueDictionary rvdpX = new RouteValueDictionary(rvd);
   rvdpX.Add("Page", grid.PageCount);
}
@hh.ActionLink(">>", pageActionName, rvdpX)
</li>
</ul>
}
</div>
}
@helper DoAjaxPager(System.Web.Mvc.AjaxHelper aa, System.Web.Mvc.Ajax.AjaxOptions aopts, System.Web.Mvc.HtmlHelper hh, string pageActionName, WebGrid grid, int maxPageLinks, object rvd) {
<div class="pager">
<div class="pageof">Page <b>@(grid.PageIndex + 1)</b> of <b>@grid.PageCount</b></div>
@if (grid.PageCount > 1) {
<ul>
<li>
@{ RouteValueDictionary rvdp1 = new RouteValueDictionary(rvd);
   rvdp1.Add("Page", 1);
}
@aa.ActionLink("<<", pageActionName, rvdp1, aopts)
</li>
@{ int start = Math.Max(0, grid.PageIndex - maxPageLinks / 2); }
@for (int ix = 0; ix + start < grid.PageCount; ix++) {
    int pageno = start + ix + 1;
    var css = hh.Raw(pageno - 1 == grid.PageIndex ? " class=\"highlighted\"" : "");
    RouteValueDictionary rvdp = new RouteValueDictionary(rvd);
    rvdp.Add("Page", pageno);
<li@css>
@aa.ActionLink(pageno.ToString(), pageActionName, rvdp, aopts)
</li>
    if (ix >= maxPageLinks) { break; }
}
<li>
@{ RouteValueDictionary rvdpX = new RouteValueDictionary(rvd);
   rvdpX.Add("Page", grid.PageCount);
}
@aa.ActionLink(">>", pageActionName, rvdpX, aopts)
</li>
</ul>
}
</div>
}
<center>
@LocalHelpers.DoPager(Html, "Index", grid, 10, new { CurrentFilter = ViewBag.CurrentFilter })
</center>
@grid.Table(
    tableStyle: "centerit",
    columns: grid.Columns(
        grid.Column(format: @<span>@Html.ActionLink("Edit", "Edit", new { id = item.ID }) | @Html.ActionLink("Details", "Details", new { id = item.ID }) | @Html.ActionLink("Delete", "Delete", new { id = item.ID })</span>),
            grid.Column("PartNumber", "Part Number"),
            grid.Column("Description", "Description"),
            grid.Column("Regex", "Regex")
            )
        )
<center>
@LocalHelpers.DoPager(Html, "Index", grid, 10, new { CurrentFilter = ViewBag.CurrentFilter })
</center>

In my view, I am recycling the "CurrentFilter" to know what to filter on. This connects to the Controller Action (not pictured).

What about sorting? Is route information preserved for the sorting links?

It is set up to pass through any values you choose to "regenerate" like sorting parameters, filter parameters, etc. but you must put them in where you are adding the grid. If you look at the last parameter, that is the place to put stuff you want to "come back" to your action.

thanks for the flame old boy i don't even do it this way i was just trying to address the question, that's what this site is about! It's not minus so some people found it useful, again the point of this site.

Asp.net Mvc3 webgrid and paging - Stack Overflow

asp.net-mvc-3 webgrid
Rectangle 27 1

My answer envolves keeping your search on Session, and nothing more than that. The solution is good because you can adapt it to your real world situation, and doesnt need specific classes or JQuery.

[HttpGet]
    public ActionResult Index()//My default action result that will render the grid at its default situation
    {
        SearchViewModel model = new SearchViewModel(); 

        if (Request.IsAjaxRequest()) //First trick is here, this verification will tell you that someone sorted or paged the grid.
        {
            if (Session["SearchViewModel"] != null) //If session is not empty, you will get the last filtred values from it.
                model = (SearchViewModel)Session["SearchViewModel"];
        }
        else // If it is not an AjaxRequest, you have to clear your Session, so new requests to Index with default behavior won't display filtred values.
        {
            Session["SearchViewModel"] = null;
        }

        model.GridResult = ExecuteFilter(model); // OPITIONAL! This code dependes on how is your real world situation. Just remember that you need to return a default behavior grid if the request was not called by the WebGrid, or return filtred results if WebGrid requested.
        return View(model);
    }

So, this will be your default ActionResult. It will verify if the request was called by the WebGrid paging or sorting event, to decide if returns filtred results or normal behavior result.

Next step is the search POST ActionResult:

[HttpPost]
    public ActionResult Index(SearchViewModel pesquisa) // IMPORTANT!! It is necessary to be the SAME NAME of your GET ActionResult. The reason for that I know, but won't discuss here because it goes out of the question.
    {
        SearchViewModel model = new SearchViewModel();
        model.GridResult = ExecuteFilter(pesquisa); // Execute your filter
        Session["SearchViewModel"] = model; //Save your filter parameters on Session.
        return View("Index", model);
    }

Thats it. The Index.cshtml doesn't have any trick. Just a SearchForm to the ActionResult Index, passing my SearchViewModel as parameter.

Well, when you click to sort or page, the WebGrid execute a JavaScript similar to this:

$('#yourGrid').load('it pass the url used to display your current Page, and some paging or sorting parameters, but those are used by the WebGrid')

Since it does a .load() method, the request will be a GET, and will hit your Index GET ActionResult. But it is an AJAX call, so our magic trick will execute the filter again with the parameters you saved on Session.

The unique detail I alert, is about your default grid behavior. The GET Index ActionResult MUST EVER RETURNS a valid grid result, not matter if it has or not filters on Session.

You can change Session to Cache if its fit better.

Asp.net Mvc3 webgrid and paging - Stack Overflow

asp.net-mvc-3 webgrid
Rectangle 27 4

WebGrid can't do the paging when called after a POST method.

So modify your search control in order to have something else than a POST

c# - Paging not working in MVC Webgrid - Stack Overflow

c# asp.net-mvc
Rectangle 27 3

Should I pass the whole list of entities from Database to a WebGrid to have right paging and sorting functionallity?

No, of course not, that would be catastrophic. You should implement paging on the server. And here's another article on MSDN you may find useful.

Actually it is absolutely what I needed. I saw this article but was so lazy to try :)

ASP.NET MVC 4 WebGrid. Load entities from Database - Stack Overflow

asp.net-mvc asp.net-mvc-3 asp.net-mvc-4 razor webgrid
Rectangle 27 4

The ajaxUpdateCallback is the name of the javascript function that will get called after the server call is complete. This would allow you to call your jQuery function after paging or sorting.

@ { var grid = new WebGrid(data, ajaxUpdateContainerId : "grid", 
            ajaxUpdateCallback: "callBack");
   }

jquery - javascript not working in MVC webgrid after sorting or paging...

jquery asp.net-mvc webgrid
Rectangle 27 38

nowadays MVC 3 now has a webGrid out of the box. I know this question is from a while ago, but I ended up on it when looking for something about webGrid. So I thought it should have an answer mentioning the new webGrid.

Here are a few good posts on how to use it:

It supports sorting, paging and also some Ajax stuff. It can do lot for you already, but you can also specify every separate column separately.

Update: There are also many JavaScript libraries available that can do the table for you. I personally like to use DataTables. You can feed it an existing html table generated on the server or give it an endpoint where it can retrieve the data (all or just one page).

Greate out-of-box functionality, ships with MVC 3, simple to use. Love it!

Paging & Sorting grids with ASP.Net MVC - Stack Overflow

asp.net asp.net-mvc gridview objectdatasource
Rectangle 27 1

I faced the same issue and resolved it after i saw 'mcaffart' comment saying the webgrid couldn't do paging right after a post method that loads the webgrid. I changed my Ajax call to GET instead of post, also marked my action method to [HTTPGET] which resulted in the paging on the webgrid functioning as expected. Thanks for your comments.

c# - Paging not working in MVC Webgrid - Stack Overflow

c# asp.net-mvc
Rectangle 27 11

Excuse the verbose data setup but this works...

@{
    var data = Enumerable.Range(0, 10).Select(i => new { Index = i, SubItems = new object[] { new { A = "A" + i, B = "B" + (i * i) } } }).ToArray();
    WebGrid topGrid = new WebGrid(data);
}

@topGrid.GetHtml(columns:
    topGrid.Columns(
        topGrid.Column("Index"),
        topGrid.Column("SubItems", format: (item) =>
        {
            WebGrid subGrid = subGrid = new WebGrid(item.SubItems);
            return subGrid.GetHtml(
                    columns: subGrid.Columns(
                        subGrid.Column("A"),
                        subGrid.Column("B")
                    )
                );
        })
    )
)

Of course you'll have to make sure in the GetHtml() method calls you give each grid (both top and sub) unique parameter names for paging/sorting or you'll end up with conflicts.

+1 I need paging only for outer grid. Inner grid will have at the most 5 to 7 rows and I might not make it more than one column. So for nested grid, I'm planning to have one long column with all Model fields formatted in it.

asp.net mvc - Razor Nested WebGrid - Stack Overflow

asp.net-mvc asp.net-mvc-3 razor paging webgrid
Rectangle 27 1

I always interpret Rows of data == @WebGrid witch has already that feature included and you can easily implement paging and sorting as well, why not using it?

if you still want to do everything manually, you can use something like

@{
    int iRow = 0;
}

@forach( var item in Model )
{
    iRow++;
    <div class="@( iRow % 2 == 0 ? "even" : "odd" )">
        @Model.SomeData @Html.TextBoxFor(m => m.SomeTextToType)
    </div>
}

the WebGrid helper just like it's cousin gridview in webforms is totally customizable, if you did webforms before, you know you could simple add a templatecolumn and append whatever controls you like, the WebGrid Helper is the same, for example as as stated in this fine article:

@grid.GetHtml(        
    columns: grid.Columns(
        grid.Column(
             "Title", 
             "Movie", 
             @<text><div style='width: 10em'>@item.Title</div></text>), ...

Thanks for proposing alternatives... What would be the code for that case with the webgrid?

you have it in the link I posted about implementing pagging

Maybe it's me... I don't find it in the article (sample with editable data inside the grid, like a textbox).

asp.net mvc 3 - Apply even/odd style in MVC editor template for List<>...

asp.net-mvc-3 editortemplates mvc-editor-templates
Rectangle 27 1

ajaxUpdateContainerId: "grid"
var grid = new WebGrid( canPage: true, rowsPerPage: Model.PageSize, canSort: true, ajaxUpdateContainerId: "grid");

You have specified an ajaxUpdateContainerId. That means your paging is AJAX based - hence the # in the href. If you want URLs, you need to remove the ajaxUpdateContainerId.

c# - Paging not working in MVC Webgrid - Stack Overflow

c# asp.net-mvc
Rectangle 27 0

If you're looking for a primarily client-side solution, I have never had any problems with jQuery's Tablesorter with Paginator plugin: http://tablesorter.com/docs/example-pager.html

If you want to do this server side, the general approach is that you are going to cache the entire result-set server side*, then make (ajax or otherwise) calls to the server specifying which records are needed. You'll pass a starting index and a number of records to return via querystring or form field (as well as some identifier for the query to make sure you're getting the right result set).

*As mrjoltcola points out in the comments, to cache or not to cache is a case by case issue, for larger result sets it may make more sense to make more db calls with smaller result sets. An alternate solution to the big-result-set problem is capping their result-set size and displaying a message advising them to make their query more specific if the threshold is exceeded. I would advise going with your best judgement initially and optimizing if needed.

All good except for the caching. We usually just pass the page range to the db, repeatedly, so the query uses it in its limiting clause (LIMIT, ROWNUM). Some result sets are way too large to cache, and even with small result sets, caching may be trouble with large user base. But still a good point, as there are some apps that actually require paging a result set at the time the query was run first. Caching then becomes a requirement.

asp.net mvc - MVC3 Pagination, items per page - Stack Overflow

asp.net-mvc asp.net-mvc-3 pagination
Rectangle 27 0

Since its been a whole year since you posted this, please post an answer if you figured it out another way.

ASP.NET MVC 3 WebGrid, preserve the paging and define the route - Stac...

asp.net-mvc-3
Rectangle 27 0

There is no automatic paging of data when you use the MVC WebGrid. The paging that you see in the webgrid is used for custom paging meaning you have to handle it yourself. All the webgrid does is sends a page number to the actionresult as a parameter, and you use that page number to grab and return the set of data related to that page number (i.e. list.skip(pagesize * pagenumber).take(pagesize)). Hope this helps.

c# - URL of Page 2 in Asp.net MVC WebGrid - Stack Overflow

c# jquery asp.net-mvc
Rectangle 27 0

If you look at how the webgrid is being generated, you will noticed that grid.GetHtml returns an IHtmlString.

You can actually convert it to a string and replace what ever you want to replace. In your case, you want to replace the paging url.

var html = grid.GetHtml(...).ToHtmlString().Replace("home/index?page", "home/MyPartialGrid?page");

You can then create a new instance of MvcHtmlString to generate the grid.

var htmlString = new MvcHtmlString(html);
<div id="myPartialGrid">
    @htmlString
</div>

c# - URL of Page 2 in Asp.net MVC WebGrid - Stack Overflow

c# jquery asp.net-mvc