在 ASP.NET Web Form 專案中加入 Bootstrap 套件

Bootstrap 是由 Twitter 所開發的一個免費的網頁框架, 它提供了許多從基本到進階的 CSS 和 JavaScript 功能, 讓網頁開發者可以很快速地把網頁架起來, 同時還兼顧了還算不錯的美感。通常, 網頁設計師不會、也不懂得美工設計, 所以我們如果只是很單地把網頁建立起來, 很不幸的, 這個網頁通常不會跟「美觀」這兩個字有交集。但是有了 Bootstrap, 你的網頁很容易就能讓人為之驚艷 (尤其是跟之前的做法對比的話)。
當然, 我不是說 Bootstrap 從此會讓美工人員丟掉工作。我相信美工人員也會感謝 Bootstrap 的存在, 這樣至少可以讓網頁在進行 layout 時省去一些功夫, 能夠早一點下班。
其實 Bootstrap 的應用方式並不難, 但是對於完全沒有概念的人, 仍然存在著一點門檻。在這裡, 讓我花點篇幅解釋一下...

Bootstrap 是由 Twitter 所開發的一個免費的網頁框架, 它提供了許多從基本到進階的 CSS 和 JavaScript 功能, 讓網頁開發者可以很快速地把網頁架起來, 同時還兼顧了還算不錯的美感。通常, 網頁設計師不會、也不懂得美工設計, 所以我們如果只是很單地把網頁建立起來, 很不幸的, 這個網頁通常不會跟「美觀」這兩個字有交集。但是有了 Bootstrap, 你的網頁很容易就能讓人為之驚艷 (尤其是跟之前的做法對比的話)。

當然, 我不是說 Bootstrap 從此會讓美工人員丟掉工作。我相信美工人員也會感謝 Bootstrap 的存在, 這樣至少可以讓網頁在進行 layout 時省去一些功夫, 能夠早一點下班。其實 Bootstrap 的應用方式並不難, 但是對於完全沒有概念的人, 仍然存在著一點門檻。在這裡, 讓我花點篇幅解釋一下。

Bootstrap 基礎

說穿了, 對初學者而言, 你只需要搞懂兩點, 就可以掌掃 Bootstrap 的基礎原理。第一點, 就是它的所謂 Grid 系統; 第二點, 就是藉由加入元件的 CSS 類別以更改它的長相。以下, 我會做個簡單地說明。

所謂的 Grid 系統, 你不要顧名思義, 以為它跟 ASP.NET 的 GridView 控制項有任何關係。事實上, 這兩者一點關係也沒有。

但是如果你把它想像為就是像 Excel 的那種格線布置, 或者 HTML 的 <table> 元件, 你應該就能立刻進入情況。

當你打開 Excel 時, 一張空的工作表應該長得像如下的樣子:

Bootstrap 01

這是一張十二欄的表。

如果你要使用這個表來畫你的網頁的 Layout 的話, 或許你會這樣畫:

Bootstrap 02

這麼一來, Header 就是一個橫跨十二欄寬的區塊, 然後左邊的 Navigation 佔兩個欄寬、Content 佔去右邊十個欄寬, 而最下方的 Footer 又是橫跨十二個欄寬。

Bootstrap 框架的 Grid 系統就是基於類似的原理而設計的。所以, 你只需要在程式中這樣寫就行了:


<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Basic Layout</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <link href="Content/bootstrap.css" rel="stylesheet" />
    <link href="Content/bootstrap-responsive.css" rel="stylesheet" />
    <style type="text/css"> div { border: 1px solid; } </style>
</head>
<body>
    <div class="container">
        <div class="row-fluid">
            <div class="span12">
                Header</div></div>
        <div class="row-fluid">
            <div class="span2">
                Navigator</div>
            <div class="span10">
                Content</div></div>
        <div class="row-fluid">
            <div class="span12">
                Footer</div></div></div>
    <script src="Scripts/jquery-1.9.1.js"></script>
    <script src="Scripts/bootstrap.js"></script>
</body>
</html>

程式 1.1 套用 Bootstrap 2 的 HTML 網頁

以上是套用 Bootstrap 2 的版本。在較新的 Visual Studio 中 (例如 VS2013), 它內建的 Bootstrap 是 3.0 版, 其語法略有不同:


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>Test Bootstrap</title>
    <link href="Content/bootstrap.min.css" rel="stylesheet" />
    <link href="Content/Site.css" rel="stylesheet" />
    <style type="text/css"> div { border: 1px solid; } </style>
</head>
<body>
    <form id="form1" runat="server">
        <div class="row">
            <div class="row-fluid">
                <div class="col-md-12">
                    Header
                </div>
            </div>
            <div class="row-fluid">
                <div class="col-md-2">
                    Navigator
                </div>
                <div class="col-md-10">
                    Content
                </div>
            </div>
            <div class="row-fluid">
                <div class="col-md-12">
                    Footer
                </div>
            </div>
        </div>
        <script src="Scripts/jquery-1.10.2.min.js"></script>
        <script src="Scripts/bootstrap.min.js"></script>
    </form>
</body>
</html>

程式 1.2 套用 Bootstrap 3 的 HTML 網頁

實際執行結果如下圖所示:

Bootstrap 03

你可以發現, 你可以藉由控制 span* 或 .col-xs-*(解析度小於768px) 或 .col-sm-* (解析度大於768px) 或 .col-md-* (解析度大於992px) 或 .col-lg-* (解析度大於1200px) 以決定每個方塊有多寬, 其方式就是在 div 元素中加入相對的 CSS 類別, 範例如上(例如 <div class="col-md-12">)。

在上面程式中, 最重要的部份有如下幾點:

  1. 請使用 HTML5 語法標示 (即第一行的 <!DOCTYPE html>)。
  2. 加上 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 這一行, 但是也可以省略。
  3. 把 bootstrap.css 這個檔案加上去。在這裡, 它的路徑是內建或由 NuGet 套件指定的; 我待會會再提到。
  4. 請注意各個 div 元素的寫法。其原則很像 table 元素, 在最外面包一個 div, 其 CSS 類別為 "container" 或是 "row" (類比為 table), 每一列都是 row (類比為 tr), 中間則是 span* (類比為 td - colspan), 每一列不要超過 12 個 span 的寬度就行。
  5. 在程式中加上 jquery 和 bootstrap.js 這兩個 JavaScript 檔案。

上述這五個注意事項就是一個 bootstrap 網頁的基本寫法。其中除了 div 群組的寫法之外, 其它部份幾乎都不需要變動。所以, 你也許可以看出來, 這個框架非常適合以 ASP.NET 的 Master Page 來實作。不過, 為了讓這個範例程式容易被了解, 所以我把每個 Div 元素都加上邊框。實際上不需要這樣做。

如果你的網頁是從較舊的 Visual Studio 升級上來的話, 你可以把 Bootstrap 2 改成 Bootstrap 3; 詳細的做法請看 Bootstrap 3.0 的「Migrating from 2.x to 3.0」文件。

在 ASP.NET 專案中取得 Bootstrap

你可以從 Bootstrap 官網中下載 Bootstrap, 也可以從 VS2012 中直接下載並安裝 (VS2013 建立的 Web Form 專案已經預設會載入 Bootstrap 3.0, 無需另外安裝)。假設我現在從 VS2012 中新增了一個 ASP.NET 的 Web Form 空白專案, 我可以使用 NuGet 直接搜尋 Bootstrap 並且進行安裝: 

Bootstrap 04

安裝完畢之後, NuGet 會把相關檔案拷貝到專案的子目錄裡面:

Bootstrap 05

上圖中以黃色底色標示的部份, 就是 Bootstrap 會用到的所有檔案 (VS2013 預設載入 Bootstrap, 其路徑又略有不同, 請讀者留意)。你可以發現, NuGet 可能會一併下載 jQuery 1.9.1 的版本, 你可以自行選擇是否另外下載 1.10.2 或者 2.0.2 以上的版本。

Bootstrap 官網中, 你可以客製化 Bootstrap 的檔案內容以節省空間。如果你下載了這個客製化的版本, 那麼你可以把原來的版本覆蓋上去, 或者另外找地方放置, 或者改名; 你應該自己想清楚應該如何進行版本的管理。

值得注意的是, 在 bootstrap.css 中, 如果你搜尋一下 "../img/glyphicons-halflings.png" 和 "../img/glyphicons-halflings-white.png" 這兩個檔案的路徑是錯誤的; 你最好自己把它們的路徑改成 "/Content/images/"。其實在 bootstrap.min.css 中這兩個路徑也不太正確, 但是當我打算把它改掉時, VS2012 不幸當掉了! 第二次才成功。如果你不修正這兩個路徑的話, 那麼 Bootstrap 提供的 Icons 就無法顯示。在 VS2013 中則沒有這個問題。

套上 Master Page

仔細看看程式 1. 的寫法, 我們將發現 Bootstrap 的 Grid Layout 很容易套用到 Master Page。

以下, 我建立一個 Master Page, 內容就是從程式 1 修改而來的:


<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Default.master.cs" Inherits="IssueTracking.Content.themes.bootstrap.Default" %>
<%@ Register Src="~/Content/themes/bootstrap/ucHeader.ascx" TagPrefix="uc1" TagName="ucHeader" %>
<%@ Register Src="~/Content/themes/bootstrap/ucNavigator.ascx" TagPrefix="uc1" TagName="ucNavigator" %>
<%@ Register Src="~/Content/themes/bootstrap/ucFooter.ascx" TagPrefix="uc1" TagName="ucFooter" %>

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh-TW">
<head runat="server">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link href="/Content/bootstrap.css" rel="stylesheet" />
    <link href="/Content/bootstrap-responsive.css" rel="stylesheet" />
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <div class="container">
                <div class="row-fluid text-center">
                    <div class="span12 well">
                        <uc1:ucHeader runat="server" id="ucHeader" />
                    </div>
                </div>
                <div class="row-fluid success">
                    <div class="span2 well text-center">
                        <uc1:ucNavigator runat="server" id="ucNavigator" />
                    </div>
                    <div class="span10 well">
                        <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server" />
                    </div>
                </div>
                <div class="row-fluid">
                    <div class="span12 well text-center">
                        <uc1:ucFooter runat="server" id="ucFooter" />
                    </div>
                </div>
            </div>
        </div>
    </form>
    <script src="/Scripts/jquery-1.9.1.js"></script>
    <script src="/Scripts/bootstrap.js"></script>
</body>
</html>

程式 2. 套用 Bootstrap 的 Master Page

在這個程式中, 其架構幾乎是原封不動地從程式 1 搬過來。但是我把 Header、Navigator 和 Footer 分別使用三個 User Control 予以取代, 如此我們只需個別修改這三個 User Control, 在所有網頁裡就會同時生效。只有 Head 區段以及 Content 部份才套用 ContentPlaceHolder, 以方便個別網頁可以加入比較特殊的元件, 例如樣式表或者 JavaScript 等等。

接著, 我要設計一個套用這個 Master Page 的網頁:


<%@ Page Title="Test Master Page" Language="C#" MasterPageFile="~/Content/themes/bootstrap/Default.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="IssueTracking.TestMasterPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    <h2>Content</h2>
    <p><span class="badge badge-important">3</span> This is Content</p>
</asp:Content>

程式 3. 套用 Master Page 的網頁

基本上, 這個網頁和另外三個 User Control 的寫法是相當類似的。你應該依情況設計自己想要的內容。

這個網頁的長相如下:

套進 ASP.NET 控制項

當我們把網站套上 Bootstrap 之後, 我們只需對某個 HTML 標籤賦予 CSS 類別, 就可以改變該控制項的長相或行為。同樣的道理對 ASP.NET 的控制項也是有效的; 只要我們能夠將它套上 CSS 類別就行。例如, 你可以很簡單地把一個 Label 控制項加上 CSS 類別, 讓它變成一個按鈕:

<asp:Label CssClass="btn btn-danger" ID="Literal1" runat="server" >變成按鈕</asp:Label>

以下, 我將使用 GridView 作為例子:


<asp:GridView ID="GridView1" CssClass="table table-bordered table-hover">
    <Columns>
        <asp:TemplateField ShowHeader="False">
            <EditItemTemplate>
                <asp:LinkButton CommandName="Update" CssClass="btn btn-info" 
                   Text="&lt;i class=&quot;icon-play&quot;&gt;&lt;/i&gt; 更新" Width="50px">
                </asp:LinkButton> 
            <asp:LinkButton CommandName="Cancel" CssClass="btn btn-warning"
                   Text="&lt;i class=&quot;icon-stop&quot;&gt;&lt;/i&gt; 取消" Width="50px"></asp:LinkButton>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:LinkButton CommandName="Edit" CssClass="btn btn-info"
                    Text="&lt;i class=&quot;icon-edit&quot;&gt;&lt;/i&gt; 編輯" Width="50px"></asp:LinkButton> 
            <asp:LinkButton CommandName="Delete" CssClass="btn btn-warning"
                Text="&lt;i class=&quot;icon-remove&quot;&gt;&lt;/i&gt; 刪除" Width="50px"></asp:LinkButton>
            </ItemTemplate>
            <ItemStyle CssClass="text-center" />
        </asp:TemplateField>
        <asp:BoundField>
            <HeaderStyle CssClass="text-center" />
            <ItemStyle CssClass="text-center" />
        </asp:BoundField>
        </asp:TemplateField>
        <asp:TemplateField >
            <HeaderStyle CssClass="text-center" />
        </asp:TemplateField>
    <AlternatingRowStyle BackColor="#f9f9f9" />
    <HeaderStyle BackColor="#dff0d8" Font-Bold="True" />
</asp:GridView>

程式 4. 套用 Bootstrap 格式的 GridView 控制項

在上述 GridView 程式碼中, 為求精簡, 我把不需要的標籤和屬性都拿掉了, 請讀者留意。原則上, 只要控制項裡面有 CssClass 屬性, 你就可以把 Bootstrap 的 CSS 類別加上去。不過有時候你必須把某個 BoundField 轉換成 TemplateField, 才有辦法加上 CSS 類別。但是在某些狀況下, ASP.NET 所提供的功能優於使用 Bootstrap; 例如表格的交叉底色, 使用 AlternatingRowSyle 來指定, 會比使用 Bootstrap 的 table-striped 來得好。所以你可以看到我並沒有採用 table-striped。

Bootstrap 學習資源

到這裡為止, 我已經把 Bootstrap 的最重要原理講述並示範了一遍, 也教你如何套用到 ASP.NET 了。接著, 應該足夠你自己試著著手了。

要學習 Bootstrap, 我找到如下的一系列相當棒的教學影片。雖然這些影片講得非常的簡單, 而且使用英語, 但是, 請相信我, 講師的英語並沒有任何艱澀的單字, 又輔以畫面協助, 應該不難聽懂才對。由於這些影片已經把最重要基礎知識都說了, 所以我在本文中就不多贅述了。

Twitter Boostrap Tutorial 1 - Navbars

Twitter Boostrap Tutorial 2 - Fixed Navbars

Twitter Boostrap Tutorial 3 - Grid Layouts

Twitter Boostrap Tutorial 4 - Modal Dialogs

Twitter Boostrap Tutorial 5 - Dynamic Modal Dialogs

Twitter Boostrap Tutorial 6 - Tooltips

Twitter Boostrap Tutorial 7 - Table Styles

Twitter Boostrap Tutorial 8 - Forms

Twitter Boostrap Tutorial 9 - Tabs

此外, KKBruce 很佛心地把 Bootstrap 官網義務翻譯成了中文。想看中文說明的朋友可以前往參考。

注意事項

Bootstrap 框架把太多東西寫死在檔案裡面, 除了上面提過的圖檔路徑之外, 它甚至連字型都寫死為 "Helvetica Neue",Helvetica,Arial,sans-serif。因此, 如果你不想另外寫在其它的 CSS 檔案裡, 那麼或許你會想要把 bootstrap.css 和 bootstrap.min.css 改寫。不過, 如果你這麼做的話, 有兩點請特別注意:

  • 請在標頭的註解處註明這個檔案已經遭到修改, 並註明為何更改、改了什麼等等。
  • 最好把檔案的編輯方式從 ANSI 改為 UTF-8, 如此, 假設你把字體改成例如微軟正黑體, 它才會生效。

我個人則是不直接去改 bootstrap.css, 而是另外建立樣式表去覆蓋需要變更的部份。這麼做的好處是未來不需要隨著 Bootstrap 的改版而屢屢做變更, 也不會侵犯 Bootstrap 的授權精神; 壞處則是稍稍增加了瀏覽器的負擔。幸好, 我相信你會覆寫的樣式應該不會太多 (如果太多, 你何不寫一個你自己的 Bootstrap?), 所以影響應該非常有限。

補充註記: Visual Studio 2012 從 Update 3 之後, 其內建版型已和本文描述的部份細節不太一致, 讀者請留意。

參考資料:


Dev 2Share @ 點部落