服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C# 封装HtmlHelper组件:BootstrapHelper

C# 封装HtmlHelper组件:BootstrapHelper

2021-12-02 14:03C#教程网 C#

这篇文章主要介绍了C# 封装HtmlHelper组件之BootstrapHelper 的相关资料,需要的朋友可以参考下

前言:之前学习过很多的bootstrap组件,博主就在脑海里构思:是否可以封装一套自己bootstrap组件库呢。再加上看到mvc的razor语法里面直接通过后台方法输出前端控件的方式,于是打算仿照htmlhelper封装一套bootstraphelper,今天只是一个开头,讲述下如何封装自己的html组件,以后慢慢完善。

一、揭开htmlhelper的“面纱”

经常使用razor写法的园友都知道,在cshtml里面,我们可以通过后台的方法输出成前端的html组件,比如我们随便看两个例子:

C# 封装HtmlHelper组件:BootstrapHelper

输出成html之后

C# 封装HtmlHelper组件:BootstrapHelper

博主的好奇心又来了,它是怎么做到的呢?于是将html对象以及label()方法转到定义

C# 封装HtmlHelper组件:BootstrapHelper

C# 封装HtmlHelper组件:BootstrapHelper

由此可以看出html对象是htmlhelper类型的一个实例,而label()方法则是htmlhelper类型的一个扩展方法,所以就可以直接通过html.label()这种方式直接调用。

既然我们想要封装自己的htmlhelper,那么我们就必须要了解label()方法里面是如何实现的,我们伟大的reflector又派上用场了。我们来反编译system.web.mvc.dll看看。找到labelextensions这个类

C# 封装HtmlHelper组件:BootstrapHelper

经过一系列的转到定义,我们找到最终的方法

C# 封装HtmlHelper组件:BootstrapHelper

同样,我们找到textbox()最终定义的方法

C# 封装HtmlHelper组件:BootstrapHelper

哟西,原来就是tagbuilder这个一个小东西,让人觉得神奇得不要不要的。所以有时我们需要敢于反编译,或许看似高级的背后其实很简单呢~~

二、bootstraphelper组件封装准备

1、定义bootstraphelper

有了以上的基础做准备,接下来就是具体的实现了,我们新建了一个空的mvc项目,添加如下文件。

C# 封装HtmlHelper组件:BootstrapHelper

编译发现报错如下

C# 封装HtmlHelper组件:BootstrapHelper

将htmlhelper转到定义发现它有两个构造函数,分别有两个、三个参数

C# 封装HtmlHelper组件:BootstrapHelper

那么,我们的bootstraphelper也定义两个构造函数,于是代码变成这样:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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标签的扩展,它里面的基本实现如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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变量是定义在哪里的呢?再次转到定义

C# 封装HtmlHelper组件:BootstrapHelper

原来是在webviewpage这个类的子类中,同样,我们在extensions文件夹里面也新建一个webviewpage的子类bootstrapwebviewpage,实现代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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对象

C# 封装HtmlHelper组件:BootstrapHelper

怎么回事呢,html是可以找到的,那bootstrap变量去哪里了呢。。。

经过一番查找资料,发现在view文件夹里面有一个web.config文件(之前一直没怎么在意这个东西,现在想想里面还是有学问的哦),里面有一个节点system.web.webpages.razor下面有一个pages节点,默认是这样的:

?
1
2
3
4
5
6
7
8
9
10
11
12
<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

?
1
2
3
4
5
6
7
8
9
10
11
12
<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。

C# 封装HtmlHelper组件:BootstrapHelper

ok,可以找到bootstrap对象了。我们将index.cshtml里面写入如下内容:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@{
 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>

运行看看效果:

C# 封装HtmlHelper组件:BootstrapHelper

怎么还是报错呢?这个问题应该不难理解,因为在razor里面使用@调用后台变量和方法的时候也存在命名空间的概念,这个命名空间在哪里引用呢,还是在view文件夹里面的web.config里面,在system.web.webpages.razor节点下面存在namespace的节点,我们将自定义的label()扩展方法所在的命名空间加进去即可。于是配置变成这样:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<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>

再次运行

C# 封装HtmlHelper组件:BootstrapHelper

三、bootstraphelper组件完善

通过上面一系列发现坑、填坑的经历,一个最最简单的bootstraphelper组件已经基本可用。我们将labelextensions简单完善下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
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上,希望自己能够坚持下去!如果你觉得本文对你有帮助,请帮忙推荐下,您的推荐是博主坚持完善的动力。

以上所述是小编给大家介绍的c# 封装htmlhelper组件之bootstraphelper ,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!

延伸 · 阅读

精彩推荐
  • C#C#实现的文件操作封装类完整实例【删除,移动,复制,重命名】

    C#实现的文件操作封装类完整实例【删除,移动,复制,重命名】

    这篇文章主要介绍了C#实现的文件操作封装类,结合完整实例形式分析了C#封装文件的删除,移动,复制,重命名等操作相关实现技巧,需要的朋友可以参考下...

    Rising_Sun3892021-12-28
  • C#C#直线的最小二乘法线性回归运算实例

    C#直线的最小二乘法线性回归运算实例

    这篇文章主要介绍了C#直线的最小二乘法线性回归运算方法,实例分析了给定一组点,用最小二乘法进行线性回归运算的实现技巧,具有一定参考借鉴价值,需要...

    北风其凉8912021-10-18
  • C#聊一聊C#接口问题 新手速来围观

    聊一聊C#接口问题 新手速来围观

    聊一聊C#接口问题,新手速来围观,一个通俗易懂的例子帮助大家更好的理解C#接口问题,感兴趣的小伙伴们可以参考一下...

    zenkey7072021-12-03
  • C#Unity3D UGUI实现缩放循环拖动卡牌展示效果

    Unity3D UGUI实现缩放循环拖动卡牌展示效果

    这篇文章主要为大家详细介绍了Unity3D UGUI实现缩放循环拖动展示卡牌效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参...

    诗远3662022-03-11
  • C#C#基础之泛型

    C#基础之泛型

    泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能。接下来通过本文给大家介绍c#基础之泛型,感兴趣的朋友一起学习吧...

    方小白7732021-12-03
  • C#c#学习之30分钟学会XAML

    c#学习之30分钟学会XAML

    一个界面程序的核心,无疑就是界面和后台代码,而xaml就是微软为构建应用程序界面而创建的一种描述性语言,也就是说,这东西是搞界面的...

    C#教程网8812021-12-10
  • C#浅谈C# winForm 窗体闪烁的问题

    浅谈C# winForm 窗体闪烁的问题

    下面小编就为大家带来一篇浅谈C# winForm 窗体闪烁的问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...

    C#教程网7962021-12-21
  • C#C# 后台处理图片的几种方法

    C# 后台处理图片的几种方法

    本篇文章主要介绍了C# 后台处理图片的几种方法,非常具有实用价值,需要的朋友可以参考下。...

    IT小伙儿10162021-12-08