C# 封裝HtmlHelper組件:BootstrapHelper
前言:之前學(xué)習(xí)過(guò)很多的Bootstrap組件,博主就在腦海里構(gòu)思:是否可以封裝一套自己Bootstrap組件庫(kù)呢。再加上看到MVC的Razor語(yǔ)法里面直接通過(guò)后臺(tái)方法輸出前端控件的方式,于是打算仿照HtmlHelper封裝一套BootstrapHelper,今天只是一個(gè)開頭,講述下如何封裝自己的Html組件,以后慢慢完善。
一、揭開HtmlHelper的“面紗”
經(jīng)常使用Razor寫法的園友都知道,在cshtml里面,我們可以通過(guò)后臺(tái)的方法輸出成前端的html組件,比如我們隨便看兩個(gè)例子:
輸出成Html之后
博主的好奇心又來(lái)了,它是怎么做到的呢?于是將Html對(duì)象以及Label()方法轉(zhuǎn)到定義
由此可以看出Html對(duì)象是HtmlHelper類型的一個(gè)實(shí)例,而Label()方法則是HtmlHelper類型的一個(gè)擴(kuò)展方法,所以就可以直接通過(guò)Html.Label()這種方式直接調(diào)用。
既然我們想要封裝自己的HtmlHelper,那么我們就必須要了解Label()方法里面是如何實(shí)現(xiàn)的,我們偉大的Reflector又派上用場(chǎng)了。我們來(lái)反編譯System.Web.MVC.dll看看。找到LabelExtensions這個(gè)類
經(jīng)過(guò)一系列的轉(zhuǎn)到定義,我們找到最終的方法
同樣,我們找到TextBox()最終定義的方法
喲西,原來(lái)就是TagBuilder這個(gè)一個(gè)小東西,讓人覺(jué)得神奇得不要不要的。所以有時(shí)我們需要敢于反編譯,或許看似高級(jí)的背后其實(shí)很簡(jiǎn)單呢~~
二、BootstrapHelper組件封裝準(zhǔn)備
1、定義BootstrapHelper
有了以上的基礎(chǔ)做準(zhǔn)備,接下來(lái)就是具體的實(shí)現(xiàn)了,我們新建了一個(gè)空的MVC項(xiàng)目,添加如下文件。
編譯發(fā)現(xiàn)報(bào)錯(cuò)如下
將HtmlHelper轉(zhuǎn)到定義發(fā)現(xiàn)它有兩個(gè)構(gòu)造函數(shù),分別有兩個(gè)、三個(gè)參數(shù)
那么,我們的BootstrapHelper也定義兩個(gè)構(gòu)造函數(shù),于是代碼變成這樣:
namespace Extensions { public class BootstrapHelper : System.Web.Mvc.HtmlHelper { /// <summary> /// 使用指定的視圖上下文和視圖數(shù)據(jù)容器來(lái)初始化 BootstrapHelper 類的新實(shí)例。 /// </summary> /// <param name="viewContext">視圖上下文</param> /// <param name="viewDataContainer">視圖數(shù)據(jù)容器</param> public BootstrapHelper(ViewContext viewContext, IViewDataContainer viewDataContainer) : base(viewContext, viewDataContainer) { } /// <summary> /// 使用指定的視圖上下文、視圖數(shù)據(jù)容器和路由集合來(lái)初始化 BootstrapHelper 類的新實(shí)例。 /// </summary> /// <param name="viewContext">視圖上下文</param> /// <param name="viewDataContainer">視圖數(shù)據(jù)容器</param> /// <param name="routeCollection">路由集合</param> public BootstrapHelper(ViewContext viewContext, IViewDataContainer viewDataContainer, RouteCollection routeCollection) : base(viewContext, viewDataContainer, routeCollection) { } } }
這樣通過(guò)子類復(fù)用父類的構(gòu)造函數(shù)的方式即可解決以上問(wèn)題。編譯通過(guò)!
2、定義LabelExtensions
上面我們研究過(guò)HtmlHelper,在HtmlHelper里面,不同的html組件定義了不同的Extension(擴(kuò)展),下面我們就以最簡(jiǎn)單的Label標(biāo)簽為例定義我們BootstrapHelper里面的Label標(biāo)簽。
同樣,在Extensions文件夾里面我們新建了一個(gè)文件LabelExtensions.cs,用于定義Label標(biāo)簽的擴(kuò)展,它里面的基本實(shí)現(xiàn)如下:
namespace Extensions { public static class LabelExtensions { /// <summary> /// 通過(guò)使用指定的 HTML 幫助器和窗體字段的名稱,返回Label標(biāo)簽 /// </summary> /// <param name="html">擴(kuò)展方法實(shí)例</param> /// <param name="id">標(biāo)簽的id</param> /// <param name="content">標(biāo)簽的內(nèi)容</param> /// <param name="cssClass">標(biāo)簽的class樣式</param> /// <param name="htmlAttributes">標(biāo)簽的額外屬性(如果屬性里面含有“-”,請(qǐng)用“_”代替)</param> /// <returns>label標(biāo)簽的html字符串</returns> public static MvcHtmlString Label(this BootstrapHelper html, string id, string content, string cssClass, object htmlAttributes) { //定義標(biāo)簽的名稱 TagBuilder tag = new TagBuilder("label"); //給標(biāo)簽增加額外的屬性 IDictionary<string, object> attributes = BootstrapHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); if (!string.IsNullOrEmpty(id)) { attributes.Add("id", id); } if (!string.IsNullOrEmpty(cssClass)) { //給標(biāo)簽增加樣式 tag.AddCssClass(cssClass); } //給標(biāo)簽增加文本 tag.SetInnerText(content); tag.AddCssClass("control-label"); tag.MergeAttributes(attributes); return MvcHtmlString.Create(tag.ToString()); } } }
我們暫且只定義一個(gè)方法,其他的重載我們很好擴(kuò)展,這里給所有的BootstrapHelper里面的Label標(biāo)簽統(tǒng)一添加了“control-label”樣式,當(dāng)然,如果你的項(xiàng)目里面的label標(biāo)簽定義了自己的樣式,那么這里改成你需要的樣式即可。以上代碼都比較基礎(chǔ),這里就不一一講解。
3、定義BootstrapWebViewPage
以上定義了BootstrapHelper和LabelExtensions,準(zhǔn)備工作是做好了,但是還少一個(gè)對(duì)象,比如我們?cè)赾shtml頁(yè)面里面@Html.Label("姓名")這樣寫,Html變量是一個(gè)HtmlHelper類型的對(duì)象,那么,如果我們需要使用類似@Bootstrap.Label()這種寫法,以此類推,Bootstrap變量應(yīng)該也是一個(gè)BootstrapHelper類型的對(duì)象,那么如果我們要這么用,必須要先定義一個(gè)Bootstrap變量,這個(gè)變量到底在哪里定義呢。于是博主思考,Html變量是定義在哪里的呢?再次轉(zhuǎn)到定義
原來(lái)是在WebViewPage這個(gè)類的子類中,同樣,我們?cè)贓xtensions文件夾里面也新建一個(gè)WebViewPage的子類BootstrapWebViewPage,實(shí)現(xiàn)代碼如下:
namespace Extensions { public abstract class BootstrapWebViewPage<T> : System.Web.Mvc.WebViewPage<T> { //在cshtml頁(yè)面里面使用的變量 public BootstrapHelper Bootstrap { get; set; } /// <summary> /// 初始化Bootstrap對(duì)象 /// </summary> public override void InitHelpers() { base.InitHelpers(); Bootstrap = new BootstrapHelper(ViewContext, this); } public override void Execute() { //throw new NotImplementedException(); } } }
至于這里的泛型,我們以后再來(lái)做講解,這里先不做過(guò)多糾結(jié)
4、實(shí)踐
有了以上三步,所有需要的方法和變量都齊全了,貌似已經(jīng)“萬(wàn)事俱備只欠東風(fēng)”了,是不是這樣呢?我們來(lái)試一把
編譯,將Index.cshtml頁(yè)面關(guān)閉重新打開,發(fā)現(xiàn)仍然找不到Bootstrap對(duì)象
怎么回事呢,Html是可以找到的,那Bootstrap變量去哪里了呢。。。
經(jīng)過(guò)一番查找資料,發(fā)現(xiàn)在View文件夾里面有一個(gè)web.config文件(之前一直沒(méi)怎么在意這個(gè)東西,現(xiàn)在想想里面還是有學(xué)問(wèn)的哦),里面有一個(gè)節(jié)點(diǎn)system.web.webPages.razor下面有一個(gè)pages節(jié)點(diǎn),默認(rèn)是這樣的:
<system.web.webPages.razor> <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <pages pageBaseType="System.Web.Mvc.WebViewPage"> <namespaces> <add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Routing" /> <add namespace="BootstrapHelper" /> </namespaces> </pages> </system.web.webPages.razor>
我們將pages節(jié)點(diǎn)的pageBaseType改成我們的WebViewPage
<system.web.webPages.razor> <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <pages pageBaseType="Extensions.BootstrapWebViewPage"> <namespaces> <add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Routing" /> <add namespace="BootstrapHelper" /> </namespaces> </pages> </system.web.webPages.razor>
然后編譯,重新打開Index.cshtml。
OK,可以找到Bootstrap對(duì)象了。我們將Index.cshtml里面寫入如下內(nèi)容:
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div> @Html.Label("姓名") @Html.TextBox("a", "Jim") @Bootstrap.Label(null, "Bootstrap Label標(biāo)簽", null, null) </div> </body> </html>
運(yùn)行看看效果:
怎么還是報(bào)錯(cuò)呢?這個(gè)問(wèn)題應(yīng)該不難理解,因?yàn)樵趓azor里面使用@調(diào)用后臺(tái)變量和方法的時(shí)候也存在命名空間的概念,這個(gè)命名空間在哪里引用呢,還是在View文件夾里面的web.config里面,在system.web.webPages.razor節(jié)點(diǎn)下面存在namespace的節(jié)點(diǎn),我們將自定義的Label()擴(kuò)展方法所在的命名空間加進(jìn)去即可。于是配置變成這樣:
<system.web.webPages.razor> <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" /> <pages pageBaseType="Extensions.BootstrapWebViewPage"> <namespaces> <add namespace="System.Web.Mvc" /> <add namespace="System.Web.Mvc.Ajax" /> <add namespace="System.Web.Mvc.Html" /> <add namespace="System.Web.Routing" /> <add namespace="BootstrapHelper" /> <add namespace="Extensions"/> </namespaces> </pages> </system.web.webPages.razor>
再次運(yùn)行
三、BootstrapHelper組件完善
通過(guò)上面一系列發(fā)現(xiàn)坑、填坑的經(jīng)歷,一個(gè)最最簡(jiǎn)單的BootstrapHelper組件已經(jīng)基本可用。我們將LabelExtensions簡(jiǎn)單完善下:
namespace Extensions { public static class LabelExtensions { public static MvcHtmlString Label(this BootstrapHelper html, string id) { return Label(html, id, null, null, null); } public static MvcHtmlString Label(this BootstrapHelper html, string content) { return Label(html, null, content, null, null); } public static MvcHtmlString Label(this BootstrapHelper html, string id, string content) { return Label(html, id, content, null, null); } public static MvcHtmlString Label(this BootstrapHelper html, string id, string content, object htmlAttributes) { return Label(html, id, content, null, htmlAttributes); } /// <summary> /// 通過(guò)使用指定的 HTML 幫助器和窗體字段的名稱,返回Label標(biāo)簽 /// </summary> /// <param name="html">擴(kuò)展方法實(shí)例</param> /// <param name="id">標(biāo)簽的id</param> /// <param name="content">標(biāo)簽的內(nèi)容</param> /// <param name="cssClass">標(biāo)簽的class樣式</param> /// <param name="htmlAttributes">標(biāo)簽的額外屬性(如果屬性里面含有“-”,請(qǐng)用“_”代替)</param> /// <returns>label標(biāo)簽的html字符串</returns> public static MvcHtmlString Label(this BootstrapHelper html, string id, string content, string cssClass, object htmlAttributes) { //定義標(biāo)簽的名稱 TagBuilder tag = new TagBuilder("label"); //給標(biāo)簽增加額外的屬性 IDictionary<string, object> attributes = BootstrapHelper.AnonymousObjectToHtmlAttributes(htmlAttributes); if (!string.IsNullOrEmpty(id)) { attributes.Add("id", id); } if (!string.IsNullOrEmpty(cssClass)) { //給標(biāo)簽增加樣式 tag.AddCssClass(cssClass); } //給標(biāo)簽增加文本 tag.SetInnerText(content); tag.AddCssClass("control-label"); tag.MergeAttributes(attributes); return MvcHtmlString.Create(tag.ToString()); } } }
呵呵,是不是有模有樣~~可能又有人要說(shuō)博主“山寨”了,呵呵,不管山寨不山寨,你覺(jué)得爽就行。
四、總結(jié)
這篇先到這里,一路填坑,基本功能總算可用。還有一些需要完善的地方,比如泛型,比如lamada表達(dá)式等等,來(lái)日方長(zhǎng),博主有時(shí)間完善下。還有最基礎(chǔ)的一些表單控件,我們都需要封裝,這個(gè)估計(jì)還有點(diǎn)工作量,只能慢慢來(lái)完善了,等完善都一定的程度會(huì)開源在git上,希望自己能夠堅(jiān)持下去!如果你覺(jué)得本文對(duì)你有幫助,請(qǐng)幫忙推薦下,您的推薦是博主堅(jiān)持完善的動(dòng)力。
以上所述是小編給大家介紹的C# 封裝HtmlHelper組件之BootstrapHelper ,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)我們網(wǎng)站的支持!
上一篇:C#環(huán)形緩沖區(qū)(隊(duì)列)完全實(shí)現(xiàn)
欄 目:C#教程
下一篇:C#實(shí)現(xiàn)讀取指定盤符硬盤序列號(hào)的方法
本文標(biāo)題:C# 封裝HtmlHelper組件:BootstrapHelper
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/6315.html
您可能感興趣的文章
- 01-10C#操作LINQ to SQL組件進(jìn)行數(shù)據(jù)庫(kù)建模的基本教程
- 01-10C# 面向?qū)ο笕筇匦裕悍庋b、繼承、多態(tài)
- 01-10適用于WebForm Mvc的Pager分頁(yè)組件C#實(shí)現(xiàn)
- 01-10C#組件系列 你值得擁有的一款Excel處理神器Spire.XLS
- 01-10C#實(shí)現(xiàn)的微信網(wǎng)頁(yè)授權(quán)操作邏輯封裝示例
- 01-10C#Url操作類封裝、仿Node.Js中的Url模塊實(shí)例
- 01-10談一談autofac組件的實(shí)例范圍
- 01-10C# 重寫ComboBox實(shí)現(xiàn)下拉任意組件的方法
- 01-10C#使用第三方組件生成二維碼匯總
- 01-10C#通過(guò)第三方組件生成二維碼(QR Code)和條形碼(Bar Code)


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻 器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10C#中split用法實(shí)例總結(jié)
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改