Wie mache ich eine Paginierung in ASP.NET MVC?

85

Was ist die am meisten bevorzugte und einfachste Methode zur Paginierung in ASP.NET MVC? Das heißt, was ist der einfachste Weg, eine Liste in mehrere durchsuchbare Seiten aufzuteilen.

Nehmen wir als Beispiel an, ich erhalte eine Liste von Elementen aus einer Datenbank / einem Gateway / einem Repository wie folgt:

public ActionResult ListMyItems()
{
    List<Item> list = ItemDB.GetListOfItems();
    ViewData["ItemList"] = list;

    return View();
}

Der Einfachheit halber möchte ich nur eine Seitenzahl für meine Aktion als Parameter angeben. So was:

public ActionResult ListMyItems(int page)
{
   //...
}
Spoike
quelle

Antworten:

106

Was ist die Datenquelle? Ihre Aktion kann einige Standardargumente enthalten, z

ActionResult Search(string query, int startIndex, int pageSize) {...}

Standardmäßig im Routen-Setup, sodass startIndex 0 und pageSize (sagen wir) 20 ist:

        routes.MapRoute("Search", "Search/{query}/{startIndex}",
                        new
                        {
                            controller = "Home", action = "Search",
                            startIndex = 0, pageSize = 20
                        });

Um den Feed zu teilen, können Sie LINQ ganz einfach verwenden:

var page = source.Skip(startIndex).Take(pageSize);

(oder multiplizieren Sie, wenn Sie "pageNumber" anstelle von "startIndex" verwenden)

Mit LINQ-toSQL, EF usw. sollte dies auch bis in die Datenbank "komponieren".

Sie sollten dann in der Lage sein, Aktionslinks zur nächsten Seite (usw.) zu verwenden:

<%=Html.ActionLink("next page", "Search", new {
                query, startIndex = startIndex + pageSize, pageSize }) %>
Marc Gravell
quelle
3
Das ist ein interessantes Routing-Beispiel, also werde ich es positiv bewerten. Ich bin noch nicht in den Groove der Verwendung von LINQ geraten, daher ist Skip and Take für mich neu. Aber genau das brauche ich. Und deshalb werde ich dies als Antwort markieren.
Spoike
tolles Zeug! Danke vielmals.
Ric Tokyo
Bei Verwendung von MVC2 ActionLinkgibt mir Ihre Syntax beim Anfordern der Seite einen Kompilierungsfehler. CS0103: Der Name 'startIndex' existiert im aktuellen Kontext nicht. Ist diese Technik mit MVC2 nicht möglich?
Comecme
@comecme meinst du die letzte Zeile? Sie müssen diese Werte (oder Variablen) angeben. Was ist dieser Startindex / diese Seitengröße?
Marc Gravell
1
Ja, ich meine die letzte Zeile. Ich dachte du benutzt den Strom startIndexund fügst pageSizeihn hinzu. Ich hatte gehofft, dass es automatisch die Werte des letzten Aufrufs von verwenden würde Search. Wie würde ich das startIndexvom letzten Searchin meinem verwenden ActionLink?
Comecme
16

Ich hatte das gleiche Problem und fand eine sehr elegante Lösung für eine Pager-Klasse aus

http://blogs.taiga.nl/martijn/2008/08/27/paging-with-aspnet-mvc/

In Ihrem Controller sieht der Anruf folgendermaßen aus:

return View(partnerList.ToPagedList(currentPageIndex, pageSize));

und aus Ihrer Sicht:

<div class="pager">
    Seite: <%= Html.Pager(ViewData.Model.PageSize, 
                          ViewData.Model.PageNumber,
                          ViewData.Model.TotalItemCount)%>
</div>
Oliver
quelle
Es ist für ASP.NET MVC Preview 5. Funktioniert es für ASP.NET MVC Beta?
Spoike
Link geändert, Code auf RC1 aktualisiert (schätze, es wird auch mit 1.0 funktionieren, wird jetzt ausprobiert). blogs.taiga.nl/martijn/2008/08/27/paging-with-aspnet-mvc
Palantir
15

Ich wollte einen einfachen Weg, dies zu tun, auch mit dem Frontend behandeln:

Regler:

public ActionResult Index(int page = 0)
{
    const int PageSize = 3; // you can always do something more elegant to set this

    var count = this.dataSource.Count();

    var data = this.dataSource.Skip(page * PageSize).Take(PageSize).ToList();

    this.ViewBag.MaxPage = (count / PageSize) - (count % PageSize == 0 ? 1 : 0);

    this.ViewBag.Page = page;

    return this.View(data);
}

Aussicht:

@* rest of file with view *@

@if (ViewBag.Page > 0)
{
    <a href="@Url.Action("Index", new { page = ViewBag.Page - 1 })" 
       class="btn btn-default">
        &laquo; Prev
    </a>
}
@if (ViewBag.Page < ViewBag.MaxPage)
{
    <a href="@Url.Action("Index", new { page = ViewBag.Page + 1 })" 
       class="btn btn-default">
        Next &raquo;
    </a>
}
dav_i
quelle
2
var data = this.dataSource.Skip(page * PageSize).Take(PageSize).ToList();Benötigt ein, orderBy(o => o.Id)bevor Sie skip()|| verwenden können Abgesehen davon ist dies eine großartige Antwort, die viel mehr Gegenstimmen verdient.
Vahx
4

Hier ist ein Link , der mir dabei geholfen hat.

Es verwendet das PagedList.MVC NuGet-Paket. Ich werde versuchen, die Schritte zusammenzufassen

  1. Installieren Sie das PagedList.MVC NuGet-Paket

  2. Projekt erstellen

  3. In using PagedList; an die Steuerung

  4. Ändern Sie Ihre Aktion, um die Seite festzulegen public ActionResult ListMyItems(int? page) { List list = ItemDB.GetListOfItems(); int pageSize = 3; int pageNumber = (page ?? 1); return View(list.ToPagedList(pageNumber, pageSize)); }

  5. Fügen Sie am unteren Rand Ihrer Ansicht Paging-Links hinzu @*Your existing view*@ Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount @Html.PagedListPager(Model, page => Url.Action("Index", new { page, sortOrder = ViewBag.CurrentSort, currentFilter = ViewBag.CurrentFilter }))

Aja Enyi
quelle
1
Ich weiß, dass dies eine alte Frage ist, weshalb diese Antwort nicht viele positive Stimmen hat. Aber es sollte, da dies die beste moderne Lösung ist. PagedList Demo
omgGenerics
2

Regler

 [HttpGet]
    public async Task<ActionResult> Index(int page =1)
    {
        if (page < 0 || page ==0 )
        {
            page = 1;
        }
        int pageSize = 5;
        int totalPage = 0;
        int totalRecord = 0;
        BusinessLayer bll = new BusinessLayer();
        MatchModel matchmodel = new MatchModel();
        matchmodel.GetMatchList = bll.GetMatchCore(page, pageSize, out totalRecord, out totalPage);
        ViewBag.dbCount = totalPage;
        return View(matchmodel);
    }

Geschäftslogik

  public List<Match> GetMatchCore(int page, int pageSize, out int totalRecord, out int totalPage)
    {
        SignalRDataContext db = new SignalRDataContext();
        var query = new List<Match>();
        totalRecord = db.Matches.Count();
        totalPage = (totalRecord / pageSize) + ((totalRecord % pageSize) > 0 ? 1 : 0);
        query = db.Matches.OrderBy(a => a.QuestionID).Skip(((page - 1) * pageSize)).Take(pageSize).ToList();
        return query;
    }

Ansicht zur Anzeige der Gesamtseitenzahl

 if (ViewBag.dbCount != null)
    {
        for (int i = 1; i <= ViewBag.dbCount; i++)
        {
            <ul class="pagination">
                <li>@Html.ActionLink(@i.ToString(), "Index", "Grid", new { page = @i },null)</li> 
            </ul>
        }
    }
DotNetLover
quelle
2

Ich denke, der einfachste Weg, eine Paginierung in einer ASP.NET MVC-Anwendung zu erstellen, ist die Verwendung der PagedList-Bibliothek.

Das folgende Github-Repository enthält ein vollständiges Beispiel. Hoffe es würde helfen.

public class ProductController : Controller
{
    public object Index(int? page)
    {
        var list = ItemDB.GetListOfItems();

        var pageNumber = page ?? 1; 
        var onePageOfItem = list.ToPagedList(pageNumber, 25); // will only contain 25 items max because of the pageSize

        ViewBag.onePageOfItem = onePageOfProducts;
        return View();
    }
}

Demo Link: http://ajaxpagination.azurewebsites.net/

Quellcode: https://github.com/ungleng/SimpleAjaxPagedListAndSearchMVC5

LENG UNG
quelle
1

Entität

public class PageEntity
{
    public int Page { get; set; }
    public string Class { get; set; }
}

public class Pagination
{
    public List<PageEntity> Pages { get; set; }
    public int Next { get; set; }
    public int Previous { get; set; }
    public string NextClass { get; set; }
    public string PreviousClass { get; set; }
    public bool Display { get; set; }
    public string Query { get; set; }
}

HTML

<nav>
    <div class="navigation" style="text-align: center">
        <ul class="pagination">
            <li class="page-item @Model.NextClass"><a class="page-link" href="?page=@(@[email protected])">&laquo;</a></li>
            @foreach (var item in @Model.Pages)
            {
                <li class="page-item @item.Class"><a class="page-link" href="?page=@([email protected])">@item.Page</a></li>
            }
            <li class="page-item @Model.NextClass"><a class="page-link" href="?page=@(@[email protected])">&raquo;</a></li>
        </ul>
    </div>
 </nav>

Paging-Logik

public Pagination GetCategoryPaging(int currentPage, int recordCount, string query)
{
    string pageClass = string.Empty; int pageSize = 10, innerCount = 5;

    Pagination pagination = new Pagination();
    pagination.Pages = new List<PageEntity>();
    pagination.Next = currentPage + 1;
    pagination.Previous = ((currentPage - 1) > 0) ? (currentPage - 1) : 1;
    pagination.Query = query;

    int totalPages = ((int)recordCount % pageSize) == 0 ? (int)recordCount / pageSize : (int)recordCount / pageSize + 1;

    int loopStart = 1, loopCount = 1;

    if ((currentPage - 2) > 0)
    {
        loopStart = (currentPage - 2);
    }

    for (int i = loopStart; i <= totalPages; i++)
    {
        pagination.Pages.Add(new PageEntity { Page = i, Class = string.Empty });

        if (loopCount == innerCount)
        { break; }

        loopCount++;
    }

    if (totalPages <= innerCount)
    {
        pagination.PreviousClass = "disabled";
    }

    foreach (var item in pagination.Pages.Where(x => x.Page == currentPage))
    {
        item.Class = "active";
    }

    if (pagination.Pages.Count() <= 1)
    {
        pagination.Display = false;
    }

    return pagination;
}

Controller verwenden

public ActionResult GetPages()
{
    int currentPage = 1; string search = string.Empty;
    if (!string.IsNullOrEmpty(Request.QueryString["page"]))
    {
        currentPage = Convert.ToInt32(Request.QueryString["page"]);
    }

    if (!string.IsNullOrEmpty(Request.QueryString["q"]))
    {
        search = "&q=" + Request.QueryString["q"];
    }
    /* to be Fetched from database using count */
    int recordCount = 100;

    Place place = new Place();
    Pagination pagination = place.GetCategoryPaging(currentPage, recordCount, search);

    return PartialView("Controls/_Pagination", pagination);
}
Kishu
quelle
Was ist die "Place" -Klasse?
FreeVice
1
public ActionResult Paging(int? pageno,bool? fwd,bool? bwd)        
{
    if(pageno!=null)
     {
       Session["currentpage"] = pageno;
     }

    using (HatronEntities DB = new HatronEntities())
    {
        if(fwd!=null && (bool)fwd)
        {
            pageno = Convert.ToInt32(Session["currentpage"]) + 1;
            Session["currentpage"] = pageno;
        }
        if (bwd != null && (bool)bwd)
        {
            pageno = Convert.ToInt32(Session["currentpage"]) - 1;
            Session["currentpage"] = pageno;
        }
        if (pageno==null)
        {
            pageno = 1;
        }
        if(pageno<0)
        {
            pageno = 1;
        }
        int total = DB.EmployeePromotion(0, 0, 0).Count();
        int  totalPage = (int)Math.Ceiling((double)total / 20);
        ViewBag.pages = totalPage;
        if (pageno > totalPage)
        {
            pageno = totalPage;
        }
        return View (DB.EmployeePromotion(0,0,0).Skip(GetSkip((int)pageno,20)).Take(20).ToList());     
    }
}

private static int GetSkip(int pageIndex, int take)
{
    return (pageIndex - 1) * take;
}

@model IEnumerable<EmployeePromotion_Result>
@{
  Layout = null;
}

 <!DOCTYPE html>

 <html>
 <head>
    <meta name="viewport" content="width=device-width" />
    <title>Paging</title>
  </head>
  <body>
 <div> 
    <table border="1">
        @foreach (var itm in Model)
        {
 <tr>
   <td>@itm.District</td>
   <td>@itm.employee</td>
   <td>@itm.PromotionTo</td>
 </tr>
        }
    </table>
    <a href="@Url.Action("Paging", "Home",new { pageno=1 })">First  page</a> 
    <a href="@Url.Action("Paging", "Home", new { bwd =true })"><<</a> 
    @for(int itmp =1; itmp< Convert.ToInt32(ViewBag.pages)+1;itmp++)
   {
       <a href="@Url.Action("Paging", "Home",new { pageno=itmp   })">@itmp.ToString()</a>
   }
    <a href="@Url.Action("Paging", "Home", new { fwd = true })">>></a> 
    <a href="@Url.Action("Paging", "Home", new { pageno =                                                                               Convert.ToInt32(ViewBag.pages) })">Last page</a> 
</div>
   </body>
  </html>
Prashant Vishwakarma
quelle