MVC學習(四)幾種分頁的實現(2)


  在第一種分頁方式中,僅僅實現了分頁,但並未有體現出MVC的優勢,沒有體現出泛型編程思想,尤其在數據量很大的時候,分頁十分緩慢,除此之外,還沒有實現很好的封裝,不是一個通用方法。

  因此,我希望只要傳入數據源以及頁碼數(采用泛型編程)便可以實現分頁功能,且使用十分的方便。

  下面就講講我的一些理解。

  在泛型編程中,數據容器一般繼承了IQueryable或者IEnumerable接口(此例中,數據源暫時繼承了這兩種接口)。

  為了調用方法方便,我決定對這兩個接口寫擴展方法。

  首先為了實現數據分頁功能,我們常常需要考慮以下六個屬性
  總頁數(TotalPage)、總數據量(TotalCount)、當前頁碼(PageIndex)、

  一頁顯示數據多少(PageSize)以及上一頁或者下一頁(IsPreviousPage/IsNextPage)

  因此,基於對象屬性,抽象出接口(IPageList),分頁方法必須繼承並實現這些屬性。

  接口IPageList代碼如下

 public interface IPageList { int TotalPage //總頁數
 { get; } int TotalCount//總數量
 { get; set; } int PageIndex//第幾頁
 { get; set; } int PageSize//一頁顯示幾條數據
 { get; set; } bool IsPreviousPage//是否上一頁
 { get; } bool IsNextPage { get; } }
IPageList

  實現接口,代碼如下:

public class PagedList<T>:List<T>:IPageList { public int TotalPage { return (int)Math.Ceiling((doubule)TotalCount/PageSize); } public int TotalCount { get; set; } public int PageIndex { get; set; } public int PageSize { get; set; } public bool IsPreviousPage { get { return (PageIndex>1); } } public bool IsNextPage { get { ((PageIndex) * PageSize) < TotalCount; } } }
PagedList
 讓我們看看這句代碼" public class PagedList<T>:List<T>:IPageList ",這里我們定義了一個泛型類PagedList<T>,
(其中T是一個關鍵字,T的類型可以是引用類型,也可以是值類)。在本例子,T是一個引用類型,而且是一個Model。

  首先寫一個靜態類,然后在這個靜態類中書寫靜態方法。擴展方法使您能夠向現有類型“添加”方法,而無需創建新的派生類型、重新編譯或以其他方式修改原始類型。 擴展方法是一種特殊的靜態方法,因此,擴展方法應該放在一個靜態類中。

    好,首先對IQueryable<T>進行擴展,命名方法名稱為 ToPagedList,一步一步的解析。

  返回值應該是一個泛型集合,因此,方法名可以這樣寫

      public List<T> ToPagedList<T>(this IQueryable<T> source,int? index,int? pageSize){  }

      在這里,我們可以看到,數據源的類型是IQueryable<T>,頁碼數index是可空類型(默認第一頁),每頁數據條目pageSize可空類型,默認10條數據。

  那么,如何調用這些方法的?

  初學泛型編程確實挺麻煩,思考的方式不太一樣,特別是代碼的寫法比較特殊,如果把泛型類當做普通的類來思考,就比較容易。

  我們需要一個類的屬性時,怎么去實例化呢(剔除靜態類)? 很顯然,new一個新的實例,然后去調用這個屬性(我們寫web Form頁面寫多了,很少考慮服務器控件是如何初始化的);如果想全部實例化屬性,則需要在重載構造函數中動動手腳了。

  那么,我們需要從構造函數中得到什么呢, 這才是重點。

  第一,實例化分頁的各個屬性;第二,得到當前頁碼的數據,就這兩件終級任務。

  由於我希望傳入數據源以及頁碼數便可獲得分頁數據,且考慮是在Asp.net MVC中,因此,傳入的數據要么是IQueryable<T>,要么是IEnumerable<T>,故完全可以充分利用已經存在的類型屬性為自己服務(相信微軟寫出的代碼運行效率不會太低)。在這里我會重載兩個構造函數,因為傳入的數據源的類型不同。

  我們 寫上我們需要的構造函數,第一個參數:數據源,第二個參數:當前頁碼數,第三個參數每頁顯示幾條數據。

  這里的數據源很重要,因為要繼承IQueryable或IEnumerable接口(這里需要寫兩個構造函數),以便可以使用不同的數據源。

  首先看數據源是IQueryable的構造函數,代碼如下 

public PagedList(IQueryable<T> source, int? pageIndex, int? pageSize) { if (pageIndex == null) { pageIndex = 1; }//默認顯示第一頁數據
            if (pageSize == null) { pageSize = 10; }//默認每頁顯示10條數據
            this.TotalCount = source.Count(); this.PageSize = pageSize.Value; this.PageIndex = pageIndex.Value; if (IsPreviousPage == false) { pageIndex = 1; } if (IsNextPage == false) { pageIndex = TotalPage; } int BeforePageIndex = pageIndex.Value - 1; if (BeforePageIndex < 0) { BeforePageIndex = 0; } AddRange(source.Skip((BeforePageIndex) * pageSize.Value).Take(pageSize.Value)); //如果Index是0會報錯,不能夠是負數
        } 
public PagedList(IQueryable source, int? pageIndex, int? pageSize)

  這里其實是將某一頁的數據放入了List了,因為PagedList已經繼承了List。

  既然PagedList是一個List,那么實例化后返回的值便是我們需要的數據,考慮這點,前面的ToPagedList方法返回的值就需要具體一點,而不是模糊的List<T>,應該是PagedList<T>,因此,用於對IQueryable擴展,方法也應該是靜態方法,修訂后的方法如下

 public static class Pagination { /// <summary>
        /// 返回第幾頁的數據 /// </summary>
        /// <typeparam name="T">返回的數據類型</typeparam>
        /// <param name="source">數據源,數據源需繼承IQueryable接口</param>
        /// <param name="index">第幾頁</param>
        /// <param name="pageSize">每頁顯示的數據條數,默認每頁顯示10條數據</param>
        /// <returns></returns>
        public static PagedList<T> ToPagedList<T>(this IQueryable<T> source, int? index, int? pageSize) { return new PagedList<T>(source, index, pageSize); } }
public static class Pagination

  分頁類准備好后,就是調用了。直接看代碼吧

public ActionResult FY2(string GoFlag, string PageIndex) { int PageSize = 5; int TotalCount = LzsDB.MyTestPages.Count();//獲得此數據表中數據記錄數
            double PageCount = Math.Ceiling((double)TotalCount / (double)PageSize);//獲得總頁數
            int NowPageIndex = 1; if (!string.IsNullOrEmpty(PageIndex)) { int ErrorPageIndex = 1; if (!Int32.TryParse(PageIndex, out ErrorPageIndex))//如果不能轉換成整數,則默認當前頁碼為1
 { PageIndex = "1"; } NowPageIndex = Convert.ToInt32(PageIndex);//  } GoFlag = string.IsNullOrEmpty(GoFlag) ? "First" : GoFlag; switch (GoFlag) { case "First": ViewBag.P2Index = 1; NowPageIndex = 1; break; case "Pre": ViewBag.P2Index = Convert.ToInt32(PageIndex) - 1; NowPageIndex = Convert.ToInt32(PageIndex) - 1; break; case "Next": ViewBag.P2Index = Convert.ToInt32(PageIndex) + 1; NowPageIndex = Convert.ToInt32(PageIndex) + 1; break; case "Last": ViewBag.P2Index = PageCount; NowPageIndex = Convert.ToInt32(PageCount); break; } var MyTestPagesList = LzsDB.MyTestPages.OrderBy(a => a.Id); return View(MyTestPagesList.ToPagedList(NowPageIndex, 5)); }
FY2(string GoFlag, string PageIndex)

   分頁后的效果如下

  

  我插入了120萬條數據,每頁顯示5條,在本機測試,分頁還是蠻快的。

  

  整個源程序點此下載,本例子是vs2010,MVC3,配置好數據庫便可運行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM