使用WebGrid Helper自訂分頁

by vivid 28. 六月 2017 15:07

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:
N170618402
出刊日期: 2017/6/28

本文將介紹如何在MVC 5的專案之中,使用HTML WebGrid Helper顯示自訂分頁的表格資料。

 

WebGrid Helper

WebGrid Helper 最早是ASP.NET Web Pages的功能之一,在MVC 3版時便將此功能加入,可以讓你在MVC的檢視之中顯示多筆資料。

WebGrid Helper提供以下功能:

  • 自動生成HTML <table>標籤來顯示表格式資料。
  • 支援套用CSS做格式化
  • 提供排序與分頁的功能。

WebGrid常用的屬性:

  • Source:資料來源。
  • rowsPerPage:一頁顯示幾筆,預設是10筆。
  • canPage:是否允許分頁。
  • canSort:是否允許排序。

建立範例專案

為了方便說明,我們先使用Visual Studio 2015來建立MVC 5的網站,從「File」-「New」-「Project」,在「New Project」對話盒中,確認視窗上方.NET Framework的目標版本為「.NET Framework 4.6」以上,選取左方「Installed」-「Templates」-「Visual C#」程式語言,從「Web」分類中,選取「ASP.NET Web Application(.NET Framework)」,適當設定專案名稱與專案存放路徑,按下「OK」鍵,請參考下圖所示:

clip_image002

圖 1:建立MVC 5專案。

在「New ASP.NET Web Application」對話盒中選取「MVC」,勾選下方的「MVC」項目,然後按一下畫面中的「OK」 按鈕,請參考下圖所示:

clip_image004

圖 2:勾選下方的「MVC」項目。

使用反向工程建立ADO.NET實體資料模型

下一步是使用反向工程的功能來定義模型,我們想要從SQL Server的Northwind範例資料庫來建立模型。在MVC的專案之中,通常將ADO.NET實體資料模型的相關程式置於Models資料夾之中。

從Visual Studio 2015開發工具-「Solution Explorer」- 專案-「Models」目錄上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Item」,開啟「Add New Item」對話盒,請參考下圖所示:

clip_image006

圖 3:加入新項目。

在「Add New Item」對話盒選取「ADO.NET Entity Data Model」,設定名稱為「NorthwindContext」,請參考下圖所示:

clip_image008

圖 4:建立ADO.NET實體資料模型。

然後選取「Code First from database」,按下「Next」按鈕,請參考下圖所示:

clip_image010

圖 5:選取「Code First from database」。

在下一個畫面,選取「Northwind」資料庫,建立資料庫連接,請參考下圖所示:

clip_image012

圖 6:連結到資料庫。

按「Next」按鈕進入到下一個畫面,以選取資料庫物件,請參考下圖所示:

clip_image014

圖 7:選取資料表。

當精靈完成之後,專案中Models資料夾內將產生多個CS檔案。

 

設計控制器

修改HomeController類別的程式碼,查詢出Northwind資料庫中Customers資料表資料,利用View()方法傳遞到檢視:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebGridDemo.Models;

namespace WebGridDemo.Controllers
{
    public class HomeController : Controller
    {
        NorthwindContext _db = new NorthwindContext();
        public ActionResult Index()
        {
            return View(_db.Customers.ToList());
        }
    }
}


在檢視使用WebGrid

修改_Layout.cshtml檔案,在</head>標籤上方,加入以下CSS程式碼,為WebGrid自訂顯示樣式:

<style>
     .grid1 {
         margin: 15px;
         border-collapse: collapse;
         width: 500px;
         background-color: #ffffff;
     }

     .headerStyle,.footerStyle {
         background-color: #39c5fb;
         font-weight: bold;
         color: #FFF;
     }

     .grid1 th, .grid1 td {
         border: 1px solid #C0C0C0;
         padding: 5px;
     }

     .alternatingRowStyle {
         background-color: #E4E9F5;
         color: #000;
     }
</style>


 

使用WebGrid Helper

修改Index.cshtml檢視,利用WebGrid顯示表格資料,建立WebGrid物件,叫用GetHtml()方法來產生HTML表格:

@model  IEnumerable<WebGridDemo.Models.Customer>
@{
    ViewBag.Title = "Home Page";
    WebGrid grid = new WebGrid();
    grid.Bind(Model);
}


@grid.GetHtml(
fillEmptyRows: false,
rowStyle: "rowStyle",
alternatingRowStyle: "alternatingRowStyle",
headerStyle: "headerStyle",
footerStyle: "footerStyle",
mode: WebGridPagerModes.All,
firstText: "<< 第一筆",
previousText: "< 上一筆",
nextText: "下一筆 >",
lastText: "最後一筆 >>",
columns: new[] {
grid.Column("CustomerID",header: "客戶編號", canSort: false),
grid.Column("CompanyName",header: "公司名稱", canSort: true),
grid.Column("City",header: "城市"),
grid.Column("Country",header: "國家")
},
htmlAttributes: new { @class = "grid1" }
)

 

從「Solution Explorer」視窗- 選取Views\Index資料夾下的Index.cshtml檔案,按CTRL+F5執行Index 檢視,執行結果參考如下,當你點選表頭的超連結就可以進行升冪或降冪的排序:

clip_image016

圖 8:使用WebGrid分頁與排序。

目前的程式碼,每次進行分頁或排序,會重新從資料庫將Customers資料表所有資料取回,這樣會降低執行效能,我們可以改用自訂分頁的方式來處理。

 

自訂分頁

在專案根目錄加入一個ViewModel資料夾,從Visual Studio 2015開發工具-「Solution Explorer」- 專案上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Folder」,設定名稱為「ViewModel」。

在ViewModel資料夾定義PagedViewModel類別。從Visual Studio 2015開發工具-「Solution Explorer」- 專案-「ViewModel」資料夾上方按滑鼠右鍵,從快捷選單選擇「Add」- 「New Item」,開啟「Add New Item」對話盒,選取Class,設定名稱為「PagedViewModel」,然後按下「Add」按鈕,建立新類別。

接著在PagedViewModel類別加入以下程式碼,定義PageSize、RowCount與Customers三個屬性:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WebGridDemo.Models;

namespace WebGridDemo.ViewModel
{
    public class PagedViewModel
    {
        public int PageSize { get; set; }
        public int RowCount { get; set; }
        public IEnumerable<Customer> Customers { get; set; }
    }
}

 

下一步在控制器撰寫排序以及資料分頁邏輯。修改HomeController類別程式碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebGridDemo.Models;
using WebGridDemo.ViewModel;

namespace WebGridDemo.Controllers
{
    public class HomeController : Controller
    {
        NorthwindContext _db = new NorthwindContext();
        public ActionResult Index(int page = 1, string sort = "CustomerId", string sortdir = "ASC")
        {
            const int pageSize = 5;
            IQueryable<Customer> customers = from c in _db.Customers select c;

            switch (sort)
            {
                case "CompanyName":
                    customers = (sortdir == "ASC") ? customers.OrderBy(c => c.CompanyName) : customers.OrderByDescending(c => c.CompanyName);
                    break;
                case "City":
                    customers = (sortdir == "ASC") ? customers.OrderBy(c => c.City) : customers.OrderByDescending(c => c.City);
                    break;
                case "Country":
                    customers = (sortdir == "ASC") ? customers.OrderBy(c => c.Country) : customers.OrderByDescending(c => c.Country);
                    break;
                default:
                    customers = (sortdir == "ASC") ? customers.OrderBy(c => c.CustomerID) : customers.OrderByDescending(c => c.CustomerID);
                    break;
            }

            var vm = new PagedViewModel()
            {
                RowCount = _db.Customers.Count(),
                PageSize = 5,
                Customers = customers.Skip((page - 1) * pageSize).Take(pageSize).ToList()
            };
            return View(vm);
        }
    }
}

 

接著修改Index檢視,加入以下程式碼,設定WebGrid每頁要顯示的資料筆數,並叫用Bind()方法,設定資料來源和資料總筆數:

@model  WebGridDemo.ViewModel.PagedViewModel
@{
    ViewBag.Title = "Home Page";
    WebGrid grid = new WebGrid(rowsPerPage: Model.PageSize);
    grid.Bind(Model.Customers,
    autoSortAndPage: false,
    rowCount: Model.RowCount);
}


@grid.GetHtml(
fillEmptyRows: false,
rowStyle: "rowStyle",
alternatingRowStyle: "alternatingRowStyle",
headerStyle: "headerStyle",
footerStyle: "footerStyle",
mode: WebGridPagerModes.All,
firstText: "<< 第一筆",
previousText: "< 上一筆",
nextText: "下一筆 >",
lastText: "最後一筆 >>",
columns: new[] {
grid.Column("CustomerID",header: "客戶編號", canSort: false),
grid.Column("CompanyName",header: "公司名稱", canSort: true),
grid.Column("City",header: "城市"),
grid.Column("Country",header: "國家")
},
htmlAttributes: new { @class = "grid1" }
)

 

從「Solution Explorer」視窗- 選取Views\Index資料夾下的Index.cshtml檔案,按CTRL+F5執行Index 檢視,執行結果和上例看起來類似。不過若我們在網頁點選第二頁,實際上會送出以下SQL指令,只挑出符合第二頁的5筆資料來做顯示:

SELECT
    [Extent1].[CustomerID] AS [CustomerID],
    [Extent1].[CompanyName] AS [CompanyName],
    [Extent1].[ContactName] AS [ContactName],
    [Extent1].[ContactTitle] AS [ContactTitle],
    [Extent1].[Address] AS [Address],
    [Extent1].[City] AS [City],
    [Extent1].[Region] AS [Region],
    [Extent1].[PostalCode] AS [PostalCode],
    [Extent1].[Country] AS [Country],
    [Extent1].[Phone] AS [Phone],
    [Extent1].[Fax] AS [Fax]
    FROM [dbo].[Customers] AS [Extent1]
    ORDER BY [Extent1].[CustomerID] ASC
    OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY ". The command text "SELECT
    [Extent1].[CustomerID] AS [CustomerID],
    [Extent1].[CompanyName] AS [CompanyName],
    [Extent1].[ContactName] AS [ContactName],
    [Extent1].[ContactTitle] AS [ContactTitle],
    [Extent1].[Address] AS [Address],
    [Extent1].[City] AS [City],
    [Extent1].[Region] AS [Region],
    [Extent1].[PostalCode] AS [PostalCode],
    [Extent1].[Country] AS [Country],
    [Extent1].[Phone] AS [Phone],
    [Extent1].[Fax] AS [Fax]
    FROM [dbo].[Customers] AS [Extent1]
    ORDER BY [Extent1].[CustomerID] ASC
    OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY

 

加入選取資料功能

接下來我們要再擴充WebGrid的功能,我們想要讓客戶編號欄位變成超連結,點選畫面中的任一筆客戶資料超連結,就在網頁下方顯示客戶詳細資訊,請參考下圖所示:

clip_image018

圖 9:加入選取功能。

修改Index檢視,修改Web Grid的CustomerID欄位,叫用GetSelectLink()方法產生超連結,然後在檢視Web Grid下方,利用grid.Rows[grid.SelectedIndex].Value取得選到的Customer資料,顯示詳細資料:

@model  WebGridDemo.ViewModel.PagedViewModel
@{
    ViewBag.Title = "Home Page";
    WebGrid grid = new WebGrid(rowsPerPage: Model.PageSize);
    grid.Bind(Model.Customers,
    autoSortAndPage: false,
    rowCount: Model.RowCount);
}


@grid.GetHtml(
fillEmptyRows: false,
rowStyle: "rowStyle",
alternatingRowStyle: "alternatingRowStyle",
headerStyle: "headerStyle",
footerStyle: "footerStyle",
mode: WebGridPagerModes.All,
firstText: "<< 第一筆",
previousText: "< 上一筆",
nextText: "下一筆 >",
lastText: "最後一筆 >>",
columns: new[] {
grid.Column("CustomerID",header: "客戶編號", canSort: false ,format:(item) => item.GetSelectLink(item.CustomerID)),
grid.Column("CompanyName",header: "公司名稱", canSort: true),
grid.Column("City",header: "城市"),
grid.Column("Country",header: "國家")
},
htmlAttributes: new { @class = "grid1" }
)
<div class="container">
    @if (grid.HasSelection)
    {
        WebGridDemo.Models.Customer c = grid.Rows[grid.SelectedIndex].Value;
        <div class="row">
            <div class="col-md-4">
                Customer ID
            </div>
            <div class="col-md-8" >
                @c.CustomerID
            </div>
        </div>
        <div class="row">
            <div class="col-md-4">
                Company Name
            </div>
            <div class="col-md-8">
                @c.CompanyName
            </div>
        </div>
        <div class="row">
            <div class="col-md-4">
                City
            </div>
            <div class="col-md-8">
                @c.City
            </div>
        </div>
        <div class="row">
            <div class="col-md-4">
                Country
            </div>
            <div class="col-md-8">
                @c.Country
            </div>
        </div>
        <div class="row">
            <div class="col-md-4">
                Contact Name
            </div>
            <div class="col-md-8">
                @c.ContactName
            </div>
        </div>
        <div class="row">
            <div class="col-md-4">
                Phone
            </div>
            <div class="col-md-8">
                @c.Phone
            </div>
        </div>
    }
</div>

 

從「Solution Explorer」視窗- 選取Views\Index資料夾下的Index.cshtml檔案,按CTRL+F5執行Index 檢視,目前的程式碼,每次點選客戶編號超連結,會重新從資料庫將Customers資料表取回資料,並將選到的客戶詳細資料顯示在下方,這次還是抓五筆資料來顯示,參考以下送出的SQL指令:

SELECT
    [Extent1].[CustomerID] AS [CustomerID],
    [Extent1].[CompanyName] AS [CompanyName],
    [Extent1].[ContactName] AS [ContactName],
    [Extent1].[ContactTitle] AS [ContactTitle],
    [Extent1].[Address] AS [Address],
    [Extent1].[City] AS [City],
    [Extent1].[Region] AS [Region],
    [Extent1].[PostalCode] AS [PostalCode],
    [Extent1].[Country] AS [Country],
    [Extent1].[Phone] AS [Phone],
    [Extent1].[Fax] AS [Fax]
    FROM [dbo].[Customers] AS [Extent1]
    ORDER BY [Extent1].[CustomerID] ASC
    OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY ". The command text "SELECT
    [Extent1].[CustomerID] AS [CustomerID],
    [Extent1].[CompanyName] AS [CompanyName],
    [Extent1].[ContactName] AS [ContactName],
    [Extent1].[ContactTitle] AS [ContactTitle],
    [Extent1].[Address] AS [Address],
    [Extent1].[City] AS [City],
    [Extent1].[Region] AS [Region],
    [Extent1].[PostalCode] AS [PostalCode],
    [Extent1].[Country] AS [Country],
    [Extent1].[Phone] AS [Phone],
    [Extent1].[Fax] AS [Fax]
    FROM [dbo].[Customers] AS [Extent1]
    ORDER BY [Extent1].[CustomerID] ASC
    OFFSET 0 ROWS FETCH NEXT 5 ROWS ONLY

 

使用AJAX

使用Web Grid進行資料分頁或排序時,若不想更新檢視中所有標籤可以將Web Grid包在一個容器標籤之中,然後設定ajaxUpdateContainerId,指定要更新的標籤,參考以下範例程式碼,此外在Index檢視上方顯示系統時間:

@model  WebGridDemo.ViewModel.PagedViewModel
@Html.Label("date", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"))
<div id="result">
    @{
        ViewBag.Title = "Home Page";
        WebGrid grid = new WebGrid(rowsPerPage: Model.PageSize, ajaxUpdateContainerId: "result");
        grid.Bind(Model.Customers,
        autoSortAndPage: false,
        rowCount: Model.RowCount);
    }

    @grid.GetHtml(
     fillEmptyRows: false,
     rowStyle: "rowStyle",
     alternatingRowStyle: "alternatingRowStyle",
     headerStyle: "headerStyle",
     footerStyle: "footerStyle",
     mode: WebGridPagerModes.All,
     firstText: "<< 第一筆",
     previousText: "< 上一筆",
     nextText: "下一筆 >",
     lastText: "最後一筆 >>",
     columns: new[] {
       grid.Column("CustomerID",header: "客戶編號", canSort: false ,format:(item) => item.GetSelectLink(item.CustomerID)),
       grid.Column("CompanyName",header: "公司名稱", canSort: true),
       grid.Column("City",header: "城市"),
       grid.Column("Country",header: "國家")
     },
     htmlAttributes: new { @class = "grid1" }
     )
    <div class="container">
        @if (grid.HasSelection)
            {
                WebGridDemo.Models.Customer c = grid.Rows[grid.SelectedIndex].Value;
            <div class="row">
                <div class="col-md-4">
                    Customer ID
                </div>
                <div class="col-md-8">
                    @c.CustomerID
                </div>
            </div>
            <div class="row">
                <div class="col-md-4">
                    Company Name
                </div>
                <div class="col-md-8">
                    @c.CompanyName
                </div>
            </div>
            <div class="row">
                <div class="col-md-4">
                    City
                </div>
                <div class="col-md-8">
                    @c.City
                </div>
            </div>
            <div class="row">
                <div class="col-md-4">
                    Country
                </div>
                <div class="col-md-8">
                    @c.Country
                </div>
            </div>
            <div class="row">
                <div class="col-md-4">
                    ContactName
                </div>
                <div class="col-md-8">
                    @c.ContactName
                </div>
            </div>
                <div class="row">
                    <div class="col-md-4">
                        Phone
                    </div>
                    <div class="col-md-8">
                        @c.Phone
                    </div>
                </div>
        }
    </div>
</div>

 

從「Solution Explorer」視窗- 選取Views\Index資料夾下的Index.cshtml檔案,按CTRL+F5執行Index 檢視,目前的程式碼,每次點選客戶編號超連結,或進行排序、分頁動作時,上方的系統時間還是會根著變動,請參考下圖所示:

clip_image020

圖 10:使用AJAX更新畫面。

修訂Layout.cshtml檔案,將引用JavaScript程式碼的這行程式:「Scripts.Render("~/bundles/jquery")」,移動到</head>標籤之中:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
    <style>
        .grid1 {
            margin: 15px;
            border-collapse: collapse;
            width: 500px;
            background-color: #ffffff;
        }

        .headerStyle,.footerStyle {
            background-color: #39c5fb;
            font-weight: bold;
            color: #FFF;
        }

        .grid1 th, .grid1 td {
            border: 1px solid #C0C0C0;
            padding: 5px;
        }

        .alternatingRowStyle {
            background-color: #E4E9F5;
            color: #000;
        }
    </style>
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
</head>
<body>
    <div class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                </ul>
            </div>
        </div>
    </div>
    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; @DateTime.Now.Year - My ASP.NET Application</p>
        </footer>
    </div>


    @RenderSection("scripts", required: false)
</body>
</html>

 

這次再執行每次點選客戶編號超連結,或進行排序、分頁動作時,上方的系統時間就不會變動,表示只更新WebGrid的標籤。

Tags:

.NET Magazine國際中文電子雜誌 | ASP.NET MVC | 許薰尹Vivid Hsu

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List