MVC学习之分页 【转】
生活随笔
收集整理的這篇文章主要介紹了
MVC学习之分页 【转】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
分頁 如果dinners列表記錄過多,為了讓用戶更方便瀏覽,我們需要實現分頁顯示,而不是一次顯示大量的記錄列表。 Index() Action方法更新 DinnersController類的Index() action方法代碼如下: ??????? // ??????? // GET: /Dinners/ ??????? public ActionResult Index() ??????? { ??????????? var dinners = dinnerRepository.FindUpcomingDinners().ToList(); ??????????? return View("Index", dinners); ??????? } 當用戶請求/Dinners地址時,將返回所有即將來臨的dinners列表,并在頁面全部顯示出來。 理解IQueryable<T> IQueryable<T> 接口是.NET 3.5的LINQ中引入的,實現了強大的deferred execution,我們將利用這一特性實現分頁功能。 在DinnerRepository類中,FindUpcommingDinners() 方法將返回IQueryable<Dinner>對象。 ??????? public IQueryable<Dinner> FindUpcomingDinners() ??????? { ??????????? return from dinner in db.Dinners ?????????????????? where dinner.EventDate > DateTime.Now ?????????????????? orderby dinner.EventDate ?????????????????? select dinner; ??????? } FindUpcomingDinners() 方法返回的IQueryable<Dinner> 對象封裝了使用LINQ to SQL從數據庫中檢索Dinner對象的查詢。重要的是,該語句并不會對數據庫執行查詢,直到我們試圖去訪問或者遍歷查詢中的數據,或者我們調用ToList() 方法。調用FindUpcomingDinners() 方法在執行查詢之前,可以選擇添加額外的操作或過濾(chained operations/filters),當查詢數據時,LINQ to SQL會聰明地對數據庫執行組合查詢。 為了執行分頁邏輯,我們更新了Index() action 方法,在調用ToList() 方法之前,對返回的IQueryable<Dinner>序列應用了附加的Skip 和Take操作符。 // // GET: /Dinners/ public ActionResult Index() { var upcomingDinners = dinnerRepository.FindUpcomingDinners(); var paginatedDinners = upcomingDinners.Skip(10).Take(10).ToList(); return View(paginatedDinners); } 上述代碼跳過數據庫中前10條即將來臨的Dinners記錄,接著返回10條記錄。LINQ to SQL聰明地構造了優化的SQL查詢,在SQL 數據庫端實現上述邏輯,僅僅返回我們想要的10條記錄,使查詢性能更加優化和可擴展性。 在URL中添加page參數值 我們將在URL中包含page參數值,標識用戶請求的分頁,而不是在代碼中硬編碼特定的頁面范圍。 使用Querystring 參數值 下面的代碼演示如何使用更新Index() action 方法,支持querystring 參數,URL地址如/Dinners?page=2。 // GET: /Dinners/ // /Dinners?page=2 public ActionResult Index(int? page) { const int pageSize = 10; var upcomingDinners = dinnerRepository.FindUpcomingDinners(); var paginatedDinners = upcomingDinners.Skip((page ?? 0) * pageSize) .Take(pageSize) .ToList(); return View(paginatedDinners); } 上述Index() 方法有一個參數page,該參數定義為nullable 整型。/Dinners?page=2 地址表示2將傳遞為參數值。/Dinners 地址(沒有querystring 參數)將傳入一個空值。 我們通過page乘以頁面記錄數(page size,本范例為10)來決定需要跳過的dinners記錄條數。同時,我們使用了C#操作符(??),該操作在處理nullable類型時,非常有用。如果page參數為空(null),上述代碼將對page賦值為0。 使用嵌入的URL參數值 除了了querystring外,另外的一個辦法是嵌入page參數到實際的URL中,如/Dinners/Page/2 或者/Dinners/2。ASP.NET MVC包含了一個強大的URL路由引擎,可以輕松支持上述場景。 我們可以注冊定制的路由規則,映射任何進來的URL或URL格式到任何Controller控制器類和Action方法。可以通過打開項目中Global.asax文件來實現。 使用MapRoute() 輔助方法,注冊一個新的映射規則,像第一次調用routes.MapRoute()方法: ??????? public static void RegisterRoutes(RouteCollection routes) ??????? { ??????????? routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); ??????????? routes.MapRoute( ??????????????? "UpcomingDinners", ??????????????? "Dinners/Page/{page}", ??????????????? new { controller = "Dinners", action = "Index" } ??????????? ); ??????????? routes.MapRoute( ??????????????? "Default",????????????????????????????????????????????? // Route name ??????????????? "{controller}/{action}/{id}",?????????????????????????? // URL with parameters ??????????????? new { controller = "Home", action = "Index", id = "" }?// Parameter defaults ??????????? ); ??????? } 在上述代碼中,我們注冊了一個新的路由規則 – UpcommingDinners,URL格式為/Dinners/Page/{page},其中{page} 是嵌入在URL的參數。MapRoute() 方法將符合上述URL格式的請求映射到DinnersController類的Index() action 方法。 我們使用與Querystring方案中完全相同的Index() 方法,處理page參數將來自于URL,而不是querystring: ??????? // ??????? // GET: /Dinners/ ??????? // /Dinners/Page/2 ??????? public ActionResult Index(int? page) ??????? { ??????????? const int pageSize = 10; ??????????? var upcomingDinners = dinnerRepository.FindUpcomingDinners(); ??????????? var paginatedDinners = upcomingDinners.Skip((page ?? 0) * pageSize) ??????????? .Take(pageSize) ??????????? .ToList(); ??????????? return View(paginatedDinners); ??????? } 現在訪問/Dinners URL時,將返回前10條記錄,而不是全部記錄了。
? 接下來訪問/Dinners/Page/1 URL時,將看到下一頁的Dinners記錄。
?
添加頁面導航界面 實現頁面分頁的最后一步是在視圖模板中添加上一頁、下一頁的導航界面,方便用戶在頁面之間切換。 為了正確實現這一步,我們需要知道數據庫中Dinners的記錄數和需要分為多少頁。接著,我們計算當前請求的頁面是開始頁或是最后頁,并正確顯示或隱藏上一頁和下一頁的導航鏈接。我們將在Index() action 方法中實現這一邏輯。另一選擇是,我們在項目中添加一個輔助類,封裝這一邏輯,實現更多地方的重用。 下面是一個簡單PaginatedList 輔助類,繼承.NET Framework 內置的List<T>集合類。它實現了一個可重用的集合類,用來在任何IQueryable序列中實現分頁。在NerdDinner范例程序中,用來對IQueryable<Dinner> 結果集進行分頁,但是它也可用于其他應用程序中對IQueryable<Product>或IQueryable<Customer>結果集進行分頁。 ??? public class PaginatedList<T> : List<T> ??? { ??????? public int PageIndex { get; private set; } ??????? public int PageSize { get; private set; } ??????? public int TotalCount { get; private set; } ??????? public int TotalPages { get; private set; } ??????? public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize) ??????? { ??????????? PageIndex = pageIndex; ??????????? PageSize = pageSize; ??????????? TotalCount = source.Count(); ??????????? TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize); ??????????? this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize)); ??????? } ??????? public bool HasPreviousPage ??????? { ??????????? get ??????????? { ??????????????? return (PageIndex > 0); ??????????? } ??????? } ??????? public bool HasNextPage ??????? { ??????????? get ??????????? { ??????????????? return (PageIndex + 1 < TotalPages); ??????????? } ??????? } ??? } 上述類公開的4個屬性,PageIndex、PageSize、TotalCount 和 TotalPages等等,另外公開了2個輔助屬性:HasPreviousPage和HasNextPage,這2個屬性分別表示是否頁面數據在集合的開始頁或者結束頁。上述代碼將引起執行2次SQL 查詢,第一次檢索Dinner Objects總記錄數(不返回對象,僅僅是執行SELECT COUNT語句,返回一個整型值),第二次檢索數據庫,返回當前頁需要的數據列表。 接著,我們更新DinnersController.Index() 輔助方法,從DinnerRepository.FindUpcomingDinners() 結果集中創建一個PaginatedList<Dinner> 對象,并傳遞給視圖模板。 ??????? // GET: /Dinners/ ??????? // /Dinners/Page/2 ??????? public ActionResult Index(int? page) ??????? { ??????????? const int pageSize = 10; ??????????? var upcomingDinners = dinnerRepository.FindUpcomingDinners(); ??????????? var paginatedDinners = new PaginatedList<Dinner>(upcomingDinners, page ?? 0, pageSize); ??????????? return View(paginatedDinners); ??????? } 接著更新\Views\Dinners\Index.aspx 視圖模板,從繼承ViewPage<IEnumerable<Dinner>>更新為ViewPage<NerdDinner.Helpers.PaginatedList<Dinner>>,然后添加如下代碼到視圖模板的底部,顯示或隱藏上一頁和下一頁的導航鏈接: ??? <% if (Model.HasPreviousPage) ?????? { %> ??? <%= Html.RouteLink("上一頁","UpcomingDinners",new { page=(Model.PageIndex-1) }) %> ??? <% } %> ??? <% if (Model.HasNextPage) ?????? { %> ??? <%= Html.RouteLink("下一頁","UpcomingDinners",new { page = (Model.PageIndex + 1) })%> ??? <% } %> 上述代碼使用Html.RouteLink() 輔助方法生成HTML超鏈接,這一方法與我們前面使用的Html.ActionLink() 輔助方法比較相似。區別是生成URL地址時,使用Global.asax文件中設置的路由規則。確保生成的URL和Index() Action方法有相同的格式:/Dinners/Page/{page} – 其中{page} 參數值基于當前頁的序號來提供。
? 現在,我們訪問NerdDinner應用程序時,每次將展示10條Dinners記錄。
? 在頁腳也提供了上一頁和下一頁的導航鏈接,實現頁面跳轉。 來自西北的狼! 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
? 接下來訪問/Dinners/Page/1 URL時,將看到下一頁的Dinners記錄。
?
添加頁面導航界面 實現頁面分頁的最后一步是在視圖模板中添加上一頁、下一頁的導航界面,方便用戶在頁面之間切換。 為了正確實現這一步,我們需要知道數據庫中Dinners的記錄數和需要分為多少頁。接著,我們計算當前請求的頁面是開始頁或是最后頁,并正確顯示或隱藏上一頁和下一頁的導航鏈接。我們將在Index() action 方法中實現這一邏輯。另一選擇是,我們在項目中添加一個輔助類,封裝這一邏輯,實現更多地方的重用。 下面是一個簡單PaginatedList 輔助類,繼承.NET Framework 內置的List<T>集合類。它實現了一個可重用的集合類,用來在任何IQueryable序列中實現分頁。在NerdDinner范例程序中,用來對IQueryable<Dinner> 結果集進行分頁,但是它也可用于其他應用程序中對IQueryable<Product>或IQueryable<Customer>結果集進行分頁。 ??? public class PaginatedList<T> : List<T> ??? { ??????? public int PageIndex { get; private set; } ??????? public int PageSize { get; private set; } ??????? public int TotalCount { get; private set; } ??????? public int TotalPages { get; private set; } ??????? public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize) ??????? { ??????????? PageIndex = pageIndex; ??????????? PageSize = pageSize; ??????????? TotalCount = source.Count(); ??????????? TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize); ??????????? this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize)); ??????? } ??????? public bool HasPreviousPage ??????? { ??????????? get ??????????? { ??????????????? return (PageIndex > 0); ??????????? } ??????? } ??????? public bool HasNextPage ??????? { ??????????? get ??????????? { ??????????????? return (PageIndex + 1 < TotalPages); ??????????? } ??????? } ??? } 上述類公開的4個屬性,PageIndex、PageSize、TotalCount 和 TotalPages等等,另外公開了2個輔助屬性:HasPreviousPage和HasNextPage,這2個屬性分別表示是否頁面數據在集合的開始頁或者結束頁。上述代碼將引起執行2次SQL 查詢,第一次檢索Dinner Objects總記錄數(不返回對象,僅僅是執行SELECT COUNT語句,返回一個整型值),第二次檢索數據庫,返回當前頁需要的數據列表。 接著,我們更新DinnersController.Index() 輔助方法,從DinnerRepository.FindUpcomingDinners() 結果集中創建一個PaginatedList<Dinner> 對象,并傳遞給視圖模板。 ??????? // GET: /Dinners/ ??????? // /Dinners/Page/2 ??????? public ActionResult Index(int? page) ??????? { ??????????? const int pageSize = 10; ??????????? var upcomingDinners = dinnerRepository.FindUpcomingDinners(); ??????????? var paginatedDinners = new PaginatedList<Dinner>(upcomingDinners, page ?? 0, pageSize); ??????????? return View(paginatedDinners); ??????? } 接著更新\Views\Dinners\Index.aspx 視圖模板,從繼承ViewPage<IEnumerable<Dinner>>更新為ViewPage<NerdDinner.Helpers.PaginatedList<Dinner>>,然后添加如下代碼到視圖模板的底部,顯示或隱藏上一頁和下一頁的導航鏈接: ??? <% if (Model.HasPreviousPage) ?????? { %> ??? <%= Html.RouteLink("上一頁","UpcomingDinners",new { page=(Model.PageIndex-1) }) %> ??? <% } %> ??? <% if (Model.HasNextPage) ?????? { %> ??? <%= Html.RouteLink("下一頁","UpcomingDinners",new { page = (Model.PageIndex + 1) })%> ??? <% } %> 上述代碼使用Html.RouteLink() 輔助方法生成HTML超鏈接,這一方法與我們前面使用的Html.ActionLink() 輔助方法比較相似。區別是生成URL地址時,使用Global.asax文件中設置的路由規則。確保生成的URL和Index() Action方法有相同的格式:/Dinners/Page/{page} – 其中{page} 參數值基于當前頁的序號來提供。
? 現在,我們訪問NerdDinner應用程序時,每次將展示10條Dinners記錄。
? 在頁腳也提供了上一頁和下一頁的導航鏈接,實現頁面跳轉。 來自西北的狼! 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的MVC学习之分页 【转】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 三维向量 交互_Blend
- 下一篇: c .net ajax,Asp.net