ASP.NET MVC使用Bootstrap系列(5)——創建ASP.NET MVC Bootstrap Helpers


序言

ASP.NET MVC允許開發者創建自定義的HTML Helpers,不管是使用靜態方法還是擴展方法。一個HTML Helper本質上其實是輸出一段HTML字符串。

HTML Helpers能讓我們在多個頁面上公用同一段HTML標記,這樣不僅提高了穩定性也便於開發者去維護。當然對於這些可重用的代碼,開發者也方便對他們進行單元測試。所以,創建ASP.NET MVC Bootstrap Helpers是及其有必要的。

內置的HTML Helpers

ASP.NET MVC內置了若干標准HTML Helpers,通過@HTML來調用這些方法在視圖引擎中解析、渲染輸出HTML內容,這允許開發者在多個視圖中重用公共的方法。

舉個栗子,以下代碼產生一個type等於text的Input ,並且其id和name都等於CustomerName,其Value等於Northwind Traders:

  1. @Html.TextBox("CustomerName","Northwind Traders");

大多數內置的HTML helpers提供傳入匿名類型為元素產生指定HTML屬性的選項,對上述的@HTML.TextBox方法稍作修改,通過傳入匿名類型設置輸出元素的style屬性:

  1. @Html.TextBox("CustomerName","Northwind Traders", new { style="background-color:Blue;" })

創建自定義的Helpers

因為Bootstrap提供了大量不同的組件,所以創建Bootstrap helpers可以在多個視圖上快速使用這些組件。在ASP.NET MVC中最簡單創建Bootstrap helpers是通過@helper語法來實現。一個自定義的helper可以包含任何HTML標記甚至Razor標記,你可以通過如下步驟來創建:

  • 在項目的根目錄創建文件夾App_Code
  • 在App_Code文件夾中新建BootstrapHelpers.cshtml文件並加入如下代碼
  1. @helper PrimaryButtonSmall(string id,string caption)
  2. {
  3.     <button id="@id" type="button" class="btn btn-primary btn-sm">@caption</button>
  4. }

上述代碼使用@helper創建了一個新的名為PrimaryButtonSmall helper,它接受2個參數,分別是Id和caption。其中,它產生一個Button類型的HTML標記並設置了Bootstrap的樣式。

注意:任何自定義的helpers必須存在App_Code文件夾中,這樣才能被ASP.NET MVC視圖識別。

  • 在視圖中通過 @BootstrapHelpers.PrimaryButtonSmall("btnSave","保存")來使用新創建的helper。
  • 它將產生如下Bootstrap HTML元素:

當然,為了讓我們的helper更加通用性,比如指定大小、樣式等,對上述稍作如下修改,增加傳入的參數:

  1. @helper Button(string style, string size, string caption, string id)
  2. {
  3.     <button id="@id" type="button" class="btn btn-@style btn-@size">@caption </button>
  4. }

現在我們可以這樣去使用:

  1. @BootstrapHelpers.Button("danger","lg","危險","btnDanger")

它將產生如下樣式的按鈕:

不過,這種方式的helper唯一的不足是你需要"hard code"傳入樣式和尺寸,這可能需要你非常熟悉Bootstrap的樣式。

使用靜態方法創建Helpers

通過靜態方法同樣也能快速方便的創建自定義Bootstrap helpers,同樣它也是返回了HTML標記,要創建靜態方法,你可以按照如下步驟來實現:

  • 添加命了Helpers的文件夾
  • 創建如下枚舉類
  1. public class ButtonHelper
  2.    {
  3.        public static MvcHtmlString Button(string caption, Enums.ButtonStyle style, Enums.ButtonSize size)
  4.        {
  5.            if (size != Enums.ButtonSize.Normal)
  6.            {
  7.                return new MvcHtmlString(string.Format("<button type=\"button\" class=\"btn btn-{0} btn-{1}\">{2}</button>", style.ToString().ToLower(), ToBootstrapSize(size), caption));
  8.            }
  9.            return new MvcHtmlString(string.Format("<button type=\"button\" class=\"btn btn-{0}\">{1}</button>", style.ToString().ToLower(), caption));
  10.        }
  11.  
  12.        private static string ToBootstrapSize(Enums.ButtonSize size)
  13.        {
  14.            string bootstrapSize = string.Empty;
  15.            switch (size)
  16.            {
  17.                case Enums.ButtonSize.Large:
  18.                    bootstrapSize = "lg";
  19.                    break;
  20.  
  21.                case Enums.ButtonSize.Small:
  22.                    bootstrapSize = "sm";
  23.                    break;
  24.  
  25.                case Enums.ButtonSize.ExtraSmall:
  26.                    bootstrapSize = "xs";
  27.                    break;
  28.            }
  29.            return bootstrapSize;
  30.        }
  31.    }

Button方法返回了一個MvcHtmlString對象,它代表了編碼過后的HTML字符。

  • 通過使用靜態方法來調用:
  1. @ButtonHelper.Button("危險", Enums.ButtonStyle.Danger, Enums.ButtonSize.Large)

你可以和之前的"hard code"寫法進行比較,盡管他們產生相同的結果:

  1. @BootstrapHelpers.Button("danger","lg","危險","btnDanger")

使用擴展方法創建Helpers

內置的ASP.NET MVC helper(@HTML)是基於擴展方法的,我們可以再對上述的靜態方法進行升級——使用擴展方法來創建Bootstrap helpers。

  • 在Helpers文件夾下創建ButtonExtensions類
  • 修改ButtonExtensions為Static類型
  • 修改Namespace為System.Web.Mvc.Html,這樣方便@HTML調用擴展方法
  • 添加擴展方法,返回MvcHtmlString
  1. public static MvcHtmlString BootstrapButton(this HtmlHelper helper, string caption, Enums.ButtonStyle style, Enums.ButtonSize size)
  2.         {
  3.             if (size != Enums.ButtonSize.Normal)
  4.             {
  5.                 return new MvcHtmlString(string.Format("<button type=\"button\" class=\"btn btn-{0} btn-{1}\">{2}</button>", style.ToString().ToLower(), ToBootstrapSize(size), caption));
  6.             }
  7.             return new MvcHtmlString(string.Format("<button type=\"button\" class=\"btn btn-{0}\">{1}</button>", style.ToString().ToLower(), caption));
  8.         }

因為BootstrapButton方法是擴展方法,通過如下方式去調用:

  1. @Html.BootstrapButton("很危險",Enums.ButtonStyle.Danger,Enums.ButtonSize.Large)

寫法雖不同,但返回的結果都是一致的。

創建Fluent Helpers

Fluent Interface(參考:http://martinfowler.com/bliki/FluentInterface.html)用於軟件開發實現了一種面向對象的API,以這種方式,它提供了更多的可讀性代碼,易於開發人員理解。通常通過鏈式編程來實現。

舉個栗子,我們將創建一個HTML helper來產生一個可關閉的警告框,使用Fluent Interface可以這樣來調用:

  1. @Html.Alert("警告").Warning().Dismissible()

所以要創建Fluent helpers,需要實現如下步驟:

  • 創建IFluentAlert實現IHtmlString接口,這是非常重要的一步,對於ASP.NET MVC Razor視圖引擎,如果@之后返回的類型實現了IHtmlString接口,那么視圖引擎會自動調用ToHtmlString()方法,返回實際的HTML標記。
  1. public interface IAlertFluent : IHtmlString
  2.     {
  3.         IAlertFluent Dismissible(bool canDismiss = true);
  4.     }
  • 創建IAlert實現IFluentAlert接口
  1. public interface IAlert : IAlertFluent
  2. {
  3.     IAlertFluent Danger();
  4.     IAlertFluent Info();
  5.     IAlertFluent Success();
  6.     IAlertFluent Warning();
  7. }
  • 創建Alert繼承IAlert接口
  1. public class Alert : IAlert
  2.    {
  3.        private Enums.AlertStyle _style;
  4.        private bool _dismissible;
  5.        private string _message;
  6.  
  7.        public Alert(string message)
  8.        {
  9.            _message = message;
  10.        }
  11.  
  12.        public IAlertFluent Danger()
  13.        {
  14.            _style = Enums.AlertStyle.Danger;
  15.            return new AlertFluent(this);
  16.        }
  17.  
  18.        public IAlertFluent Info()
  19.        {
  20.            _style = Enums.AlertStyle.Info;
  21.            return new AlertFluent(this);
  22.        }
  23.  
  24.        public IAlertFluent Success()
  25.        {
  26.            _style = Enums.AlertStyle.Success;
  27.            return new AlertFluent(this);
  28.        }
  29.  
  30.        public IAlertFluent Warning()
  31.        {
  32.            _style = Enums.AlertStyle.Warning;
  33.            return new AlertFluent(this);
  34.        }
  35.  
  36.        public IAlertFluent Dismissible(bool canDismiss = true)
  37.        {
  38.            this._dismissible = canDismiss;
  39.            return new AlertFluent(this);
  40.        }
  41.  
  42.        public string ToHtmlString()
  43.        {
  44.            var alertDiv = new TagBuilder("div");
  45.            alertDiv.AddCssClass("alert");
  46.            alertDiv.AddCssClass("alert-" + _style.ToString().ToLower());
  47.            alertDiv.InnerHtml = _message;
  48.  
  49.            if (_dismissible)
  50.            {
  51.                alertDiv.AddCssClass("alert-dismissable");
  52.                alertDiv.InnerHtml += AddCloseButton();
  53.            }
  54.  
  55.            return alertDiv.ToString();
  56.        }
  57.  
  58.        private static TagBuilder AddCloseButton()
  59.        {
  60.            var closeButton = new TagBuilder("button");
  61.            closeButton.AddCssClass("close");
  62.            closeButton.Attributes.Add("data-dismiss", "alert");
  63.            closeButton.InnerHtml = "&times;";
  64.            return closeButton;
  65.        }
  66.    }

上述代碼中,通過TagBuilder可以快速的創建HTML元素。

  • 創建AlertFluent繼承IAlertFluent
  1. public class AlertFluent : IAlertFluent
  2.     {
  3.         private readonly Alert _parent;
  4.  
  5.         public AlertFluent(Alert parent)
  6.         {
  7.             _parent = parent;
  8.         }
  9.  
  10.         public IAlertFluent Dismissible(bool canDismiss = true)
  11.         {
  12.             return _parent.Dismissible(canDismiss);
  13.         }
  14.  
  15.         public string ToHtmlString()
  16.         {
  17.             return _parent.ToHtmlString();
  18.         }
  19.     }
  • 最后創建靜態方法
  1. public static class AlertHelper
  2. {
  3.     public static Alert Alert(this HtmlHelper html,string message)
  4.     {
  5.         return new Alert(message);
  6.     }
  7. }

通過構建這種Fluent API,我們可以鏈式的去創建Bootstrap 組件,這對於不熟悉Bootstrap Framework的人來說是非常方便的,我們可以使用@HTML.Alert("Title").Danger().Dismissible()來創建如下風格的警告框:

創建自動閉合的Helpers

在ASP.NET MVC中,內置的@HTML.BeginForm() helper就是一個自動閉合的helper。當然我們也能自定義自動閉合的helpers,只要實現IDisposable接口即可。使用IDisposable接口,當對象Dispose時我們輸出元素的閉合標記,具體按照如下步驟:

  • 所以在Helpers文件夾下創建一個名為Panel的文件夾
  • 添加Panel,並實現IDisposable接口
  1. public class Panel : IDisposable
  2.     {
  3.         private readonly TextWriter _writer;
  4.  
  5.         public Panel(HtmlHelper helper, string title, Enums.PanelStyle style = Enums.PanelStyle.Default)
  6.         {
  7.             _writer = helper.ViewContext.Writer;
  8.  
  9.             var panelDiv = new TagBuilder("div");
  10.             panelDiv.AddCssClass("panel-" + style.ToString().ToLower());
  11.             panelDiv.AddCssClass("panel");
  12.  
  13.             var panelHeadingDiv = new TagBuilder("div");
  14.             panelHeadingDiv.AddCssClass("panel-heading");
  15.  
  16.             var heading3Div = new TagBuilder("h3");
  17.             heading3Div.AddCssClass("panel-title");
  18.             heading3Div.SetInnerText(title);
  19.  
  20.             var panelBodyDiv = new TagBuilder("div");
  21.             panelBodyDiv.AddCssClass("panel-body");
  22.  
  23.             panelHeadingDiv.InnerHtml = heading3Div.ToString();
  24.  
  25.             string html = string.Format("{0}{1}{2}", panelDiv.ToString(TagRenderMode.StartTag), panelHeadingDiv, panelBodyDiv.ToString(TagRenderMode.StartTag));
  26.             _writer.Write(html);
  27.         }
  28.  
  29.         public void Dispose()
  30.         {
  31.             _writer.Write("</div></div>");
  32.         }
  33.     }

上述代碼中利用Write屬性可以在當前視圖中輸出HTML標記,並在Dispose方法里輸出2個閉合的<div>標簽。

注意,我們重寫了TagBuilder的ToString()方法,只讓它生成<div>元素的開始標簽。

  • 在View中使用自動閉合的helpers
  1. @using (Html.Panel("Title", Enums.PanelStyle.Success))
  2. {
  3.     <p>這是自動閉合的Helpers</p>
  4.     <p>panel..</p>
  5. }

產生的結果如下:

小結

在這篇博客中,為了減少書寫HTML標記,我們創建了若干Bootstrap helpers來實現。這些helpers的意義在於能讓不了解Bootstrap Framework的人也能快速上手Bootstrap。

參考代碼下載


免責聲明!

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



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