ASP.NET MVC使用Bootstrap系列(3)——使用Bootstrap 組件
Bootstrap為我們提供了十幾種的可復用組件,包括字體圖標、下拉菜單、導航、警告框、彈出框、輸入框組等。在你的Web Application中使用這些組件,將為用戶提供一致和簡單易用的用戶體驗。
Bootstrap組件本質上是結合了各種現有Bootstrap元素以及添加了一些獨特Class來實現。Bootstrap元素我在上一篇文章中涉及到,具體可以參考《ASP.NET MVC使用Bootstrap系列(2)——使用Bootstrap CSS和HTML元素》。
在這篇博客中,我將繼續探索Bootstrap豐富的組件以及將它結合到ASP.NET MVC項目中。
Bootstrap 導航條
Bootstrap導航條作為"明星組件"之一,被使用在大多數基於Bootstrap Framework的網站上。為了更好的展示Bootstrap導航條,我在ASP.NET MVC的_Layout.cshtml布局頁創建一個fixed-top導航條,當然它是響應式的——在小尺寸、低分辨率的設備上打開時,它將會只展示一個按鈕並帶有3個子菜單,當點擊按鈕時垂直展示他們。在網頁上顯示如下:
在移動設備上顯示如下:
在ASP.NET MVC默認的_Layouts.cshtml布局頁中已經幫我們實現了上述功能,打開它對其稍作修改,如下代碼片段所示:

其中class為.navbar-fixed-top可以讓導航條固定在頂部,還可包含一個 .container 或 .container-fluid 容器,從而讓導航條居中,並在兩側添加內補(padding)
注意,我使用了2個局部視圖(_BackendMenuPartial和LoginPartial)來生成余下的導航條(使用.navbar-collapse類在低分辨率設備中折疊),其中局部視圖邏輯是基於當前訪問的用戶是否登陸來控制是否顯示。
首先,添加如下代碼在_BackendMenuPartial視圖中,這將會在導航條中產生一個搜索框:

因為Bootstrap導航條作為整個網站的公共部分,要實現快速搜索那么必須要知道當前所處於哪個Controller,這樣才能提高檢索效率。所以上述代碼中,增加了一個Id為fromcontroller隱藏字段,代表當前訪問的Controller。
當點擊搜索時,發送HTTP POST請求到Index Action下。然后根據傳遞過來的fromcontroller來swith到具體的Action來執行搜索,具體的搜索邏輯代碼如下:

具體搜索的Action如下:

列表組
列表組是靈活又強大的組件,不僅能用於顯示一組簡單的元素,還能結合其他元素創建一組復雜的定制內容。上面的搜索為我們重定向到Result視圖,在此視圖中,它為我們顯示了搜索結果,為了更好的展示結果,我們可以使用列表組來顯示搜索到的產品,視圖中的代碼如下所示:

在上述代碼中,為無序列表(<ul>)的class設置為list-group,並且每一個<li>的class為list-group-item,這是一個最簡單的列表組。
徽章
徽章用來高亮條目,可以很醒目的顯示新的或者未讀的條目數量,為一個元素設置徽章僅僅只需要添加<span>元素並設置它的class為badge。所以,在上述代碼的基礎上稍作修改,添加徽章,表示庫存個數,如下HTML所示:
<a href="@Url.Action("Edit","Products", new { id=@item.ProductID})" class="list-group-item"> @item.ProductName <span class="badge">@item.UnitsInStock</span> </a>
顯示的結果為如下截圖:
媒體對象
媒體對象組件被用來構建垂直風格的列表比如博客的回復或者推特。在Northwind數據庫中包含一個字段ReportTo表示Employee向另一個Employee Report。使用媒體對象可以直觀來表示這種關系。在視圖中的代碼如下所示:

顯示結果如下:
可以看到,媒體對象組件是由一系列class為media、media-heading、media-body、media-object的元素組合而成,其中media-object用來表示諸如圖片、視頻、聲音等媒體對象。
注:.pull-left 和 .pull-right 這兩個類以前也曾經被用在了媒體組件上,但是,從 v3.3.0 版本開始,他們就不再被建議使用了。.media-left 和 .media-right 替代了他們,不同之處是,在 html 結構中, .media-right 應當放在 .media-body 的后面。
頁頭
當用戶訪問網頁時,Bootstrap頁頭可以為用戶提供清晰的指示。Bootstrap頁頭本質上是一個<h1>元素被封裝在class為page-header的<div>元素中。當然你也可以利用<small>元素來提供額外的關於頁面的信息,同時Bootstrap為頁頭添加了水平分隔線用於分隔頁面,如下HTML即為我們構建了頁頭:
<div class="page-header"> <h1>員工搜索結果: <small>搜索條件: "@ViewBag.SearchQuery"</small></h1> </div>
路徑導航
路徑導航(面包屑)在Web 設計中被用來表示用戶在帶有層次的導航結構中當前頁面的位置。類似於Windows資源管理器。如下HTML所示:

在上面HTML代碼中,通過指定有序列表(<ol>)的class為breadcrumb,每一個子路徑用<li>來表示,其中通過設置<li>的class為active代表當前所處的位置。
各路徑間的分隔符已經自動通過 CSS 的 :before 和 content 屬性添加了。
分頁
分頁用來分隔列表內容,特別是顯示大量數據時通過分頁可以有效的減少服務器壓力和提高用戶體驗,如下截圖使用分頁來顯示產品列表:
要完成上述的分頁,需要安裝PagedList.Mvc程序包,在NuGet控制台中安裝即可:Install-PackagePagedList.Mvc
然后修改Action,它需要接受當然的頁碼,它是一個可空的整數類型變量,然后設置PageSize等於5,表示每頁顯示5條記錄,如下代碼所示:

public ActionResult Index(int? page) { var models = _context.Products.Project().To<ProductViewModel>().OrderBy(p => p.ProductName); int pageSize = 5; int pageNumber = (page ?? 1); return View(models.ToPagedList(pageNumber, pageSize)); }
在View中,使用PagedList動態生成分頁控件:

<div class="container"> <div class="page-header"> <h1>Products <small>Page @(Model.PageCount < Model.PageNumber ? 0 : Model.PageNumber) of @Model.PageCount</small></h1> </div> <ol class="breadcrumb"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>@Html.ActionLink("Manage", "Index", "Manage")</li> <li class="active">Products</li> </ol> <table class="table table-striped table table-hover"> <thead> <tr> <th> Product Name </th> <th> Unit Price </th> <th> Units In Stock </th> <th> Discontinued </th> <th></th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr class="@item.Status"> <td> @Html.ActionLink(item.ProductName, "Edit", new { id = item.ProductID }) </td> <td> @Html.DisplayFor(modelItem => item.UnitPrice) </td> <td> @Html.DisplayFor(modelItem => item.UnitsInStock) </td> <td> @Html.DisplayFor(modelItem => item.Discontinued) </td> <td> @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ }) </td> </tr> } </tbody> </table> @Html.PagedListPager(Model, page => Url.Action("Index", new { page }), PagedListRenderOptions.ClassicPlusFirstAndLast) <p> <a href="@Url.Action("Create","Products")" class="btn btn-sm btn-primary" role="button">Create New</a> </p> </div>
輸入框組
輸入框組為用戶在表單輸入數據時可以提供更多的額外信息。Bootstrap的輸入框組為我們在Input元素的前面或者后面添加指定class的塊,這些塊可以是文字或者字體圖標,如下所示:

<div class="form-group"> <div class="col-sm-2 input-group"> <span class="input-group-addon"> <span class="glyphicon glyphicon-phone-alt"></span> </span> @Html.TextBox("txtPhone","1194679215",new { @class = "form-control" }) </div> </div>
上面的輸入框組合中,在Textbox的左邊放置了一個帶有字體圖標Phone的灰色塊,結果如下所示:
不僅可以使用字體圖標,還可以使用純文本來顯示信息,如下所示在Textbox右邊放置了固定的郵箱域名:

當然也可以在Input元素的兩邊同時加上塊,如下代碼所示:

<div class="form-group"> <div class="col-sm-2 input-group"> <span class="input-group-addon">¥</span> @Html.TextBox("txtMoney","100",new { @class = "form-control" }) <span class="input-group-addon">.00</span> </div> </div>
按鈕式下拉菜單
按鈕式下拉菜單顧名思義,一個按鈕可以執行多種action,比如既可以Save,也可以Save之后再打開一個新的Form繼續添加記錄,如下所示:

<div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <div class="btn-group"> <button type="submit" class="btn btn-primary btn-sm">Save</button> <button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown"> <span class="caret"></span> <span class="sr-only">Toggle Dropdown</span> </button> <ul class="dropdown-menu" role="menu"> <li><a href="#" id="savenew">Save & New</a></li> <li class="divider"></li> <li><a href="#" id="duplicate">Duplicate</a></li> </ul> </div> </div> </div>
警告框
Bootstrap警告組件通常被用作給用戶提供可視化的反饋,比如當用戶Save成功后顯示確認信息、錯誤時顯示警告信息、以及其他的提示信息。
Bootstrap提供了4中不同風格的警告,如下所示:

<div class="container"> <div class="page-header"> <h1>Alerts </h1> </div> <ol class="breadcrumb"> <li>@Html.ActionLink("Home", "Index", "Home")</li> <li>Bootstrap</li> <li class="active">Alerts</li> </ol> <div class="alert alert-success"><strong>Success. </strong></div> <div class="alert alert-info"><strong>Info.</strong></div> <div class="alert alert-warning"><strong>Warning!</strong></div> <div class="alert alert-danger"><strong>Danger!</strong></div> </div>
可關閉的警告框可以讓用戶點擊右上角的X來關閉,你可以使用alter-dismissible 類:

<div class="alert alert-warning alert-Dismissible" role="alert"> <button type="button" class="close" data-dismiss="alert"> <span aria-hidden="true">×</span><span class="sr-only">Close</span> </button> <strong>Alert!</strong>這是可關閉的Alter </div>
進度條
進度條在傳統的桌面應用程序比較常見,當然也可以用在Web上。通過這些簡單、靈活的進度條,可以為當前工作流程或動作提供實時反饋。Bootstrap為我們提供了許多樣式的進度條。
-
基本進度條
基本進度條是一種純藍色的進度條,添加一個class 為sr-only 的<span>元素在進度條中是比較好的實踐,這樣能讓屏幕更好的讀取進度條的百分比。

<div class="row"> < h4>基本進度條</h4> <div class="progress"> <div class="progress-bar" role="progressbar" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100" style="width: 80%;"> <span class="sr-only">80%完成</span> </div> </div> </div>
-
上下文情景變化進度條
上下文情景變化進度條組件使用與按鈕和警告框相同的類,根據不同情境展現相應的效果。
- progress-bar-success
- progress-bar-info
- progress-bar-warning
- progress-bar-danger
-
條紋動畫效果進度條
為了讓進度條更加生動,可以為其添加條紋效果,在進度條<div>中添加class為progress-striped。當然讓進度條看起來有動畫,可以再為其指定active的class在<div>上,如下所示:

-
使用SignalR動態更新進度條
SignalR是ASP.NET的庫,可以用來雙向實時通信,在ASP.NET MVC項目中使用SignalR:1.首先通過NuGet來安裝SignalR Nuget Package:
Install-Package Microsoft.AspNet.SignalR
2.在項目里新建一個名為Hubs的文件夾,並添加ProgressbarHub類,如下代碼所示:

public class ProgressbarHub : Hub { public void SendProgress() { for (int i = 0; i <= 100; i++) { Thread.Sleep(50); Clients.Caller.sendMessage(i + "%"); } } }
SendProgress方法很簡單,向客戶端發送消息(通過自增變量輸出0—100)
3.在布局頁添加對SignalR虛擬路徑的引用:
<script src="~/signalr/hubs"></script>
4.在打包文件中,包含 SignalR.js
bundles.Add(new ScriptBundle("~/bundles/jquery").Include( "~/Scripts/jquery-{version}.js", "~/Scripts/jquery.signalR-2.2.0" ));
5.在客戶端建立與服務端的雙向通信:

@section scripts { <script type="text/javascript" language="javascript"> $(document).ready(function () { //$(".progress-bar").width('0%'); }); $("#start").click(function () { $(".progress-bar").width('0%'); var progressNotifier = $.connection.progressbarHub; progressNotifier.client.sendMessage = function (message) { updateProgress(message); }; $.connection.hub.start().done(function () { progressNotifier.server.sendProgress(); }); }); function updateProgress(message) { $(".progress-bar").width(message); $("#progressbarTitle").html(message + ' Complete'); } </script> }
你可以看到,上述代碼先初始化和服務端的連接,然后設置被服務端調用的客戶端方法updateProgress。
最后,我們建立了和服務端的連接並且啟動了服務端的操作,你可以看到,我們調用了sendProgress方法——這已經在ProgressbarHub類中定義好了。這樣當點擊ID為start的按鈕時動態為進度條更新了0-100的數值。
小結
在這篇博客中,探索了Bootstrap中豐富的組件,並將它結合到ASP.NET MVC項目中。通過實例可以發現,這類組件本質上是結合了各種現有Bootstrap元素以及添加了一些獨特Class來實現。
更多的Bootstrap組件請參見:http://v3.bootcss.com/components/