ฉันจะแบ่งหน้าใน ASP.NET MVC ได้อย่างไร


85

วิธีใดเป็นวิธีที่ต้องการและง่ายที่สุดในการแบ่งหน้าใน ASP.NET MVC นั่นคือวิธีที่ง่ายที่สุดในการแยกรายการออกเป็นหลายหน้าที่เรียกดูได้

ตัวอย่างเช่นสมมติว่าฉันได้รับรายการองค์ประกอบจากฐานข้อมูล / เกตเวย์ / ที่เก็บดังนี้:

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

    return View();
}

เพื่อความเรียบง่ายฉันต้องการระบุเพียงหมายเลขหน้าสำหรับการกระทำของฉันเป็นพารามิเตอร์ แบบนี้:

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

คำตอบ:


107

แหล่งข้อมูลคืออะไร? การกระทำของคุณอาจใช้อาร์กิวเมนต์ผิดนัดไม่กี่ข้อเช่น

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

เริ่มต้นในการตั้งค่าเส้นทางเพื่อให้ startIndex เป็น 0 และ pageSize คือ (พูด) 20:

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

ในการแยกฟีดคุณสามารถใช้ LINQ ได้อย่างง่ายดาย:

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

(หรือทำการคูณหากคุณใช้ "pageNumber" แทน "startIndex")

ด้วย LINQ-toSQL, EF และอื่น ๆ สิ่งนี้ควร "เขียน" ลงในฐานข้อมูลด้วย

จากนั้นคุณจะสามารถใช้ลิงก์การดำเนินการไปยังหน้าถัดไป (ฯลฯ ):

<%=Html.ActionLink("next page", "Search", new {
                query, startIndex = startIndex + pageSize, pageSize }) %>

3
นั่นเป็นตัวอย่างการกำหนดเส้นทางที่น่าสนใจดังนั้นฉันจะโหวตให้คะแนน ฉันยังไม่ได้ใช้ LINQ ดังนั้น Skip and Take จึงเป็นเรื่องใหม่สำหรับฉัน แต่นั่นคือสิ่งที่ฉันต้องการอย่างแน่นอน และนั่นคือเหตุผลที่ฉันจะทำเครื่องหมายนี้เป็นคำตอบ
Spoike

โคตรเจ๋ง! ขอบคุณมากในการกระทำ
Ric Tokyo

การใช้ MVC2 ActionLinkไวยากรณ์ของคุณทำให้ฉันมีข้อผิดพลาดในการคอมไพล์เมื่อขอเพจ CS0103: ไม่มีชื่อ 'startIndex' ในบริบทปัจจุบัน MVC2 ใช้เทคนิคนี้ไม่ได้หรือ?
comecme

@comecme คุณหมายถึงบรรทัดสุดท้ายหรือไม่? คุณต้องระบุค่าเหล่านั้น (หรือตัวแปร) สิ่งที่เป็นที่เริ่มต้นดัชนี / หน้าขนาด?
Marc Gravell

1
ใช่ฉันหมายถึงบรรทัดสุดท้าย ฉันคิดว่าคุณใช้กระแสstartIndexและเพิ่มpageSizeเข้าไป Searchฉันหวังว่ามันจะโดยอัตโนมัติจะใช้ค่าโทรครั้งล่าสุดที่จะ ฉันจะใช้startIndexจากครั้งสุดท้ายSearchในของฉันได้ActionLinkอย่างไร
comecme

16

ฉันมีปัญหาเดียวกันและพบวิธีแก้ปัญหาที่สวยงามมากสำหรับเพจเจอร์คลาสจาก

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

ในคอนโทรลเลอร์ของคุณการโทรดูเหมือนว่า:

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

และในมุมมองของคุณ:

<div class="pager">
    Seite: <%= Html.Pager(ViewData.Model.PageSize, 
                          ViewData.Model.PageNumber,
                          ViewData.Model.TotalItemCount)%>
</div>

สำหรับ ASP.NET MVC Preview 5 จะใช้ได้กับ ASP.NET MVC Beta หรือไม่
Spoike

ลิงก์เปลี่ยนรหัสอัปเดตเป็น RC1 (เดาว่าจะใช้ได้กับ 1.0 ด้วยจะลองใช้ตอนนี้) blogs.taiga.nl/martijn/2008/08/27/paging-with-aspnet-mvc
Palantir

16

ฉันต้องการพูดถึงวิธีง่ายๆในการทำสิ่งนี้กับส่วนหน้าด้วย:

ตัวควบคุม:

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);
}

ดู:

@* 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>
}

3
var data = this.dataSource.Skip(page * PageSize).Take(PageSize).ToList();ต้องมีorderBy(o => o.Id)ก่อนจึงจะสามารถใช้skip()|| นอกจากนี้ยังเป็นคำตอบที่ดีที่สมควรได้รับการโหวตเพิ่มขึ้นอีกมาก
Vahx

4

นี่คือลิงค์ที่ช่วยฉันในเรื่องนี้

ใช้แพ็คเกจ PagedList.MVC NuGet ฉันจะพยายามสรุปขั้นตอน

  1. ติดตั้งแพ็คเกจ PagedList.MVC NuGet

  2. สร้างโครงการ

  3. เพิ่ม using PagedList; ลงในคอนโทรลเลอร์

  4. แก้ไขการกระทำของคุณเพื่อตั้งค่าหน้า public ActionResult ListMyItems(int? page) { List list = ItemDB.GetListOfItems(); int pageSize = 3; int pageNumber = (page ?? 1); return View(list.ToPagedList(pageNumber, pageSize)); }

  5. เพิ่มลิงค์เพจที่ด้านล่างของมุมมองของคุณ @*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 }))


1
ฉันรู้ว่านี่เป็นคำถามเก่าซึ่งเป็นสาเหตุที่คำตอบนี้ไม่มีการโหวตเพิ่มขึ้นมากมาย แต่ควรเนื่องจากนี่เป็นทางออกที่ทันสมัยที่สุด PagedList Demo
omgGenerics

2

ตัวควบคุม

 [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);
    }

BusinessLogic

  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;
    }

ดูเพื่อแสดงจำนวนหน้าทั้งหมด

 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>
        }
    }

2

ฉันคิดว่าวิธีที่ง่ายที่สุดในการสร้างการแบ่งหน้าในแอปพลิเคชัน ASP.NET MVC คือการใช้ไลบรารี PagedList

มีตัวอย่างที่สมบูรณ์ในที่เก็บ github ต่อไปนี้ หวังว่ามันจะช่วยได้

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();
    }
}

ลิงค์สาธิต: http://ajaxpagination.azurewebsites.net/

รหัสที่มา: https://github.com/ungleng/SimpleAjaxPagedListAndSearchMVC5


1

เอนทิตี

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=@(@Model.Previous+@Model.Query)">&laquo;</a></li>
            @foreach (var item in @Model.Pages)
            {
                <li class="page-item @item.Class"><a class="page-link" href="?page=@(item.Page+@Model.Query)">@item.Page</a></li>
            }
            <li class="page-item @Model.NextClass"><a class="page-link" href="?page=@(@Model.Next+@Model.Query)">&raquo;</a></li>
        </ul>
    </div>
 </nav>

ตรรกะการเพจ

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;
}

การใช้คอนโทรลเลอร์

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);
}

คลาส "สถานที่" คืออะไร?
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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.