zoukankan      html  css  js  c++  java
  • 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="" })

    创建自定义的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。

    参考代码下载

    本博客为木宛城主原创,基于Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名木宛城主(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
  • 相关阅读:
    HDU 1075 What Are You Talking About(字典树)
    HDU 1075 What Are You Talking About (stl之map映射)
    HDU 1247 Hat’s Words(字典树活用)
    字典树HihoCoder
    HDU 1277全文检索(字典树)
    HDU 3294 Girls' research(manachar模板题)
    HDU 3294 Girls' research(manachar模板题)
    HDU 4763 Theme Section(KMP灵活应用)
    Ordering Tasks UVA
    Abbott's Revenge UVA
  • 原文地址:https://www.cnblogs.com/lhxsoft/p/5181028.html
Copyright © 2011-2022 走看看