MVC專案實踐,在三層架構下實現SportsStore-04,實現分頁

Darren Ji發表於2014-06-27

SportsStore是《精通ASP.NET MVC3框架(第三版)》中演示的MVC專案,在該專案中涵蓋了MVC的眾多方面,包括:使用DI容器、URL優化、導航、分頁、購物車、訂單、產品管理、影象上傳......是不錯的MVC實踐專案,但該專案不是放在多層框架下開發的,離真實專案還有一段距離。本系列將嘗試在多層框架下實現SportsStore專案,並用自己的方式實現一些功能。

 

本篇為系列第四篇,包括:

■ 7、新增分頁

 

  7、新增分頁

關於分頁,是一系列的a標籤,可以通過擴充套件HtmlHelper來實現。產生分頁a標籤的大致思路為:
1、擴充套件方法需要遍歷迴圈所有頁數,而所有頁數是由"總記錄數/頁容量",再經過計算得到。
2、可以把總記錄數、頁容量、所有頁數等封裝成一個類提供給擴充套件方法。
3、而包含總記錄數、頁容量、所有頁數等這個類例項,當然是由控制器方法提供。

 

建立PagingInfo來包裝分頁相關資訊:

using System;

namespace MySportsStore.WebUI.Models
{
    public class PagingInfo
    {
        public int TotalItems { get; set; }
        public int ItemsPerPage { get; set; }
        public int CurrentPage { get; set; }

        public int TotalPages
        {
            get { return (int)Math.Ceiling((decimal) TotalItems/ItemsPerPage); }
        }
    }
}

關於CurrentPage屬性,擴充套件方法會根據它來確定是否要給a標籤新增一個表示選中、當前頁的css屬性。

 

擴充套件方法遍歷迴圈所有頁數,產生數字a標籤,並根據PagingInfo的CurrentPage屬性來判斷是否要給a標籤加上一個用來表示選中、當前頁的屬性:

using System;
using System.Text;
using System.Web.Mvc;
using MySportsStore.WebUI.Models;

namespace MySportsStore.WebUI.HtmlHelpers
{
    public static class PagingHelpers
    {
        public static MvcHtmlString PageLinks(this HtmlHelper html,
            PagingInfo pagingInfo,
            Func<int, string> pageUrl)
        {
            StringBuilder result = new StringBuilder();
            for (int i = 1; i <= pagingInfo.TotalPages; i++)
            {
                TagBuilder tag = new TagBuilder("a");
                tag.MergeAttribute("href", pageUrl(i));
                tag.InnerHtml = i.ToString();
                if (i == pagingInfo.CurrentPage)
                {
                    tag.AddCssClass("selected");
                }
                result.Append(tag.ToString());
            }
            return MvcHtmlString.Create(result.ToString());
        }
    }
}

以上的pageUrl是一個委託,輸入頁面,輸出一個包含查詢字串的URL。

 

而新增的擴充套件方法需要在Views資料夾下的Web.config中註冊後,才能在檢視頁中使用:

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
          ......
        <add namespace="MySportsStore.WebUI.HtmlHelpers" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

當然,分頁是有關Product的分頁,在顯示Product列表的檢視頁上,除了分頁,還有一個Product的集合,於是,我們可以把分頁和Product的集合整合成一個檢視模型:

using System.Collections.Generic;
using MySportsStore.Model;

namespace MySportsStore.WebUI.Models
{
    public class ProductsListViewModel
    {
        public IEnumerable<Product>  Products { get; set; }
        public PagingInfo PagingInfo { get; set; }
    }
}

Product控制器的List方法職責很明確:就是根據前臺檢視傳遞過來表示當前頁的page變數,產生一個ProductsListViewModel的例項,傳遞給前臺檢視:

using System.Web.Mvc;
using MySportsStore.IBLL;
using MySportsStore.WebUI.Models;
using Ninject;

namespace MySportsStore.WebUI.Controllers
{
    public class ProductController : BaseController
    {
        [Inject]
        public IProductService ProductService { get; set; }

        public ProductController()
        {
            this.AddDisposableObject(ProductService);
        }

        public int PageSize = 4;
        public ViewResult List(int page = 1)
        {
            int totalCount = 0;
            ProductsListViewModel viewModel = new ProductsListViewModel()
            {
                Products = ProductService.LoadPageEntities(p => true, p => p.Id, PageSize, page, out  totalCount, true),
                PagingInfo = new PagingInfo(){CurrentPage = page, ItemsPerPage = PageSize, TotalItems = ProductService.Count(p => true)}
            };
            return View(viewModel);
        }

    }
}

Product/List.cshtml強型別檢視:

@model MySportsStore.WebUI.Models.ProductsListViewModel

@{
    ViewBag.Title = "List";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@foreach (var item in Model.Products)
{
    <div class="item">
        <h3>@item.Name</h3>
        @item.Description
        <h4>@item.Price.ToString("c")</h4>
    </div>
}

<div class="pager">
    @Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new {page = x}))
</div>

執行,得到如下結果:

10

讓人欣慰的是:對Prouct列表進行了分頁處理。稍有不足的是:頁面連結以http://localhost/?page2這種形式存在。我們在路由設定中設定如下路由:

routes.MapRoute(
                null,
                "Page{page}",
                new {controller = "Product", action = "List"}
            );

            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Product", action = "List", id = UrlParameter.Optional }
            );

執行,得到如下結果:

11

在Views/Shared/_Layout.chstml中佈局頁面,設定CSS,呈現如下頁面:

12

在Product/List.cshtml檢視頁中,還可以把顯示產品的邏輯放到一個部分檢視中,以便重複利用。在Views/Shared下建立ProductSummary.cshtml強型別部分檢視:

@model MySportsStore.Model.Product

<div class="item">
    <h3>@Model.Name</h3>
    @Model.Description
    <h4>@Model.Price.ToString("c")</h4>
</div>

最後,在Product/List.cshtml檢視頁中,在遍歷Product集合的時候,載入部分檢視:

@model MySportsStore.WebUI.Models.ProductsListViewModel

@{
    ViewBag.Title = "List";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

@foreach (var item in Model.Products)
{
   Html.RenderPartial("PrductSummary", item);
}

<div class="pager">
    @Html.PageLinks(Model.PagingInfo, x => Url.Action("List", new {page = x}))
</div>

至此,完成分頁。

原始碼在這裡

 

“MVC專案實踐,在三層架構下實現SportsStore”系列包括:

MVC專案實踐,在三層架構下實現SportsStore,從類圖看三層架構

MVC專案實踐,在三層架構下實現SportsStore-01,EF Code First建模、DAL層等

MVC專案實踐,在三層架構下實現SportsStore-02,DbSession層、BLL層

MVC專案實踐,在三層架構下實現SportsStore-03,Ninject控制器工廠等

MVC專案實踐,在三層架構下實現SportsStore-04,實現分頁

MVC專案實踐,在三層架構下實現SportsStore-05,實現導航

MVC專案實踐,在三層架構下實現SportsStore-06,實現購物車

MVC專案實踐,在三層架構下實現SportsStore-07,實現訂單提交

MVC專案實踐,在三層架構下實現SportsStore-08,部署到IIS伺服器

MVC專案實踐,在三層架構下實現SportsStore-09,ASP.NET MVC呼叫ASP.NET Web API的查詢服務

MVC專案實踐,在三層架構下實現SportsStore-10,連線字串的加密和解密

MVC專案實踐,在三層架構下實現SportsStore-11,使用Knockout實現增刪改查

相關文章