日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一步一步封装自己的HtmlHelper组件:BootstrapHelper

發布時間:2023/12/4 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一步一步封装自己的HtmlHelper组件:BootstrapHelper 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:之前學習過很多的Bootstrap組件,博主就在腦海里構思:是否可以封裝一套自己Bootstrap組件庫呢。再加上看到MVC的Razor語法里面直接通過后臺方法輸出前端控件的方式,于是打算仿照HtmlHelper封裝一套BootstrapHelper,今天只是一個開頭,講述下如何封裝自己的Html組件,以后慢慢完善。

本文原創地址:http://www.cnblogs.com/landeanfen/p/5729551.html

一、揭開HtmlHelper的“面紗”

經常使用Razor寫法的園友都知道,在cshtml里面,我們可以通過后臺的方法輸出成前端的html組件,比如我們隨便看兩個例子:

輸出成Html之后

博主的好奇心又來了,它是怎么做到的呢?于是將?Html?對象以及?Label()?方法轉到定義

由此可以看出Html對象是HtmlHelper類型的一個實例,而Label()方法則是HtmlHelper類型的一個擴展方法,所以就可以直接通過Html.Label()這種方式直接調用。不熟悉C#擴展方法的園友可以看看http://www.cnblogs.com/landeanfen/p/4632467.html。

?既然我們想要封裝自己的HtmlHelper,那么我們就必須要了解Label()方法里面是如何實現的,我們偉大的Reflector又派上用場了。我們來反編譯System.Web.MVC.dll看看。找到LabelExtensions這個類

經過一系列的轉到定義,我們找到最終的方法

同樣,我們找到TextBox()最終定義的方法

喲西,原來就是TagBuilder這個一個小東西,讓人覺得神奇得不要不要的。所以有時我們需要敢于反編譯,或許看似高級的背后其實很簡單呢~~

二、BootstrapHelper組件封裝準備

1、定義BootstrapHelper

有了以上的基礎做準備,接下來就是具體的實現了,我們新建了一個空的MVC項目,添加如下文件。

編譯發現報錯如下

將HtmlHelper轉到定義發現它有兩個構造函數,分別有兩個、三個參數

?那么,我們的BootstrapHelper也定義兩個構造函數,于是代碼變成這樣:

namespace Extensions { public class BootstrapHelper : System.Web.Mvc.HtmlHelper{ /// <summary>/// 使用指定的視圖上下文和視圖數據容器來初始化
BootstrapHelper 類的新實例。 ? ? ? ?
/// </summary>/// <param name="viewContext">視圖上下文</param>/// <param name="viewDataContainer">視圖數據容器</param>public BootstrapHelper(ViewContext viewContext,
IViewDataContainer viewDataContainer): base(viewContext, viewDataContainer){ } /// <summary>/// 使用指定的視圖上下文、視圖數據容器和路由集合來初始化
? ? ? ?/// BootstrapHelper 類的新實例。 ? ? ?
? ? ??
/// </summary>/// <param name="viewContext">視圖上下文</param>/// <param name="viewDataContainer">視圖數據容器</param>/// <param name="routeCollection">路由集合</param>public BootstrapHelper(ViewContext viewContext,
IViewDataContainer viewDataContainer, RouteCollection routeCollection): base(viewContext, viewDataContainer, routeCollection){ }} }

這樣通過子類復用父類的構造函數的方式即可解決以上問題。編譯通過!

2、定義LabelExtensions

上面我們研究過HtmlHelper,在HtmlHelper里面,不同的html組件定義了不同的Extension(擴展),下面我們就以最簡單的Label標簽為例定義我們BootstrapHelper里面的Label標簽。

同樣,在Extensions文件夾里面我們新建了一個文件LabelExtensions.cs,用于定義Label標簽的擴展,它里面的基本實現如下:

namespace Extensions {
public static class LabelExtensions{
/// <summary>/// 通過使用指定的 HTML 幫助器和窗體字段的名稱,返回Label標簽 ? ?
? ?
/// </summary>/// <param name="html">擴展方法實例</param>/// <param name="id">標簽的id</param>/// <param name="content">標簽的內容</param>/// <param name="cssClass">標簽的class樣式</param>/// <param name="htmlAttributes">標簽的額外屬性
(如果屬性里面含有“-”,請用“_”代替)
</param>/// <returns>label標簽的html字符串</returns>public static MvcHtmlString Label(this BootstrapHelper html,
string id, string content, string cssClass, object htmlAttributes){ //定義標簽的名稱TagBuilder tag = new TagBuilder("label");
//給標簽增加額外的屬性IDictionary<string, object> attributes =
BootstrapHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
if (!string.IsNullOrEmpty(id)){attributes.Add("id", id);} if (!string.IsNullOrEmpty(cssClass)){ //給標簽增加樣式tag.AddCssClass(cssClass);} //給標簽增加文本tag.SetInnerText(content);tag.AddCssClass("control-label");tag.MergeAttributes(attributes);
return MvcHtmlString.Create(tag.ToString());}} }

我們暫且只定義一個方法,其他的重載我們很好擴展,這里給所有的BootstrapHelper里面的Label標簽統一添加了“control-label”樣式,當然,如果你的項目里面的label標簽定義了自己的樣式,那么這里改成你需要的樣式即可。以上代碼都比較基礎,這里就不一一講解。

3、定義BootstrapWebViewPage

以上定義了BootstrapHelper和LabelExtensions,準備工作是做好了,但是還少一個對象,比如我們在cshtml頁面里面?@Html.Label("姓名")?這樣寫,Html變量是一個HtmlHelper類型的對象,那么,如果我們需要使用類似?@Bootstrap.Label()?這種寫法,以此類推,Bootstrap變量應該也是一個BootstrapHelper類型的對象,那么如果我們要這么用,必須要先定義一個Bootstrap變量,這個變量到底在哪里定義呢。于是博主思考,Html變量是定義在哪里的呢?再次轉到定義

原來是在WebViewPage這個類的子類中,同樣,我們在Extensions文件夾里面也新建一個WebViewPage的子類BootstrapWebViewPage,實現代碼如下:

namespace Extensions {
? ?public abstract class BootstrapWebViewPage<T> :
System.Web.Mvc.WebViewPage<T>{
//在cshtml頁面里面使用的變量public BootstrapHelper Bootstrap { get; set; }
/// <summary>/// 初始化Bootstrap對象 ? ? ?
? ? ??
/// </summary>public override void InitHelpers(){ base.InitHelpers();Bootstrap = new BootstrapHelper(ViewContext, this);} public override void Execute(){ //throw new NotImplementedException();}} }

至于這里的泛型,我們以后再來做講解,這里先不做過多糾結

?4、實踐

?有了以上三步,所有需要的方法和變量都齊全了,貌似已經“萬事俱備只欠東風”了,是不是這樣呢?我們來試一把

編譯,將Index.cshtml頁面關閉重新打開,發現仍然找不到Bootstrap對象

怎么回事呢,Html是可以找到的,那Bootstrap變量去哪里了呢。。。

經過一番查找資料,發現在View文件夾里面有一個web.config文件(之前一直沒怎么在意這個東西,現在想想里面還是有學問的哦),里面有一個節點system.web.webPages.razor下面有一個pages節點,默認是這樣的:


<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節點的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對象了。我們將Index.cshtml里面寫入如下內容:

@{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標簽", null, null)
</div></body></html>


運行看看效果:

?

怎么還是報錯呢?這個問題應該不難理解,因為在razor里面使用@調用后臺變量和方法的時候也存在命名空間的概念,這個命名空間在哪里引用呢,還是在View文件夾里面的web.config里面,在system.web.webPages.razor節點下面存在namespace的節點,我們將自定義的Label()擴展方法所在的命名空間加進去即可。于是配置變成這樣:

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

再次運行

三、BootstrapHelper組件完善

通過上面一系列發現坑、填坑的經歷,一個最最簡單的BootstrapHelper組件已經基本可用。我們將LabelExtensions簡單完善下:

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>/// 通過使用指定的 HTML 幫助器和窗體字段的名稱,返回Label標簽 ? ?
?? ?
/// </summary>/// <param name="html">擴展方法實例</param>/// <param name="id">標簽的id</param>/// <param name="content">標簽的內容</param>/// <param name="cssClass">標簽的class樣式</param>/// <param name="htmlAttributes">標簽的額外屬性
? ? ? ?(如果屬性里面含有“-”,請用“_”代替)
</param>/// <returns>label標簽的html字符串</returns>public static MvcHtmlString Label(this BootstrapHelper html,
string id, string content, string cssClass, object htmlAttributes){ //定義標簽的名稱TagBuilder tag = new TagBuilder("label");
//給標簽增加額外的屬性IDictionary<string, object> attributes =
BootstrapHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
if (!string.IsNullOrEmpty(id)){attributes.Add("id", id);} if (!string.IsNullOrEmpty(cssClass)){ //給標簽增加樣式tag.AddCssClass(cssClass);} //給標簽增加文本tag.SetInnerText(content);tag.AddCssClass("control-label");tag.MergeAttributes(attributes);
return MvcHtmlString.Create(tag.ToString());}} }

呵呵,是不是有模有樣~~可能又有人要說博主“山寨”了,呵呵,不管山寨不山寨,你覺得爽就行。

四、總結

?這篇先到這里,一路填坑,基本功能總算可用。還有一些需要完善的地方,比如泛型,比如lamada表達式等等,來日方長,博主有時間完善下。還有最基礎的一些表單控件,我們都需要封裝,這個估計還有點工作量,只能慢慢來完善了,等完善都一定的程度會開源在git上,希望自己能夠堅持下去!如果你覺得本文對你有幫助,請幫忙推薦下,您的推薦是博主堅持完善的動力。


原文地址:http://www.cnblogs.com/landeanfen/p/5729551.html


.NET社區新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關注

總結

以上是生活随笔為你收集整理的一步一步封装自己的HtmlHelper组件:BootstrapHelper的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。