• 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。

    参考代码下载

  • 相关阅读:
    operamasks—omMessageBox的使用
    operamasks-omGrid的使用
    SQL Server转sqlite数据库
    operamasks—omMessageTip的使用
    operamasks—omBorderLayout布局
    选择器(E:hover/E:active/E:focus的使用)
    CSS3(各UI元素状态伪类选择器受浏览器的支持情况)
    选择器的使用(nth-of-type和nth-last-of-type选择器)
    选择器的使用(nth-child和nth-last-child选择器)
    选择器的使用(first-child和last-child选择器)
  • 原文地址:https://www.cnblogs.com/Alex80/p/4424732.html
Copyright © 2020-2023  润新知