HTML辅助方法
概要
@Html.TextBox("xxx") @Html.EditorFor(m=>m.name) @Html.CheckBox("ccc",new people()) ……
这些都是 HtmlHelper类 的扩展方法,该类被称为HTML辅助方法或HTML辅助器,这里先记录下一些常用的HTML辅助器方法,以及如何自定义属于我们自己的扩展方法。
建立默认视图
@{ ViewBag.Title = "这是默认的视图标题"; } <h2>这是一个默认的原始视图!</h2>
编译运行可以看到:
<!DOCTYPE html> <html> <head> <title>这是默认的视图标题</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script> </head> <body> <h2>这是一个默认的原始视图!</h2> </body> </html>
可以发现, ViewBag.Title为我们生成了网页的title标签值,<h2>标签还是原生的没变。
认识MvcHtmlString
@{ ViewBag.Title = "这是默认的视图标题"; } <h2>这是一个默认的原始视图!</h2> @{ var mvcHtmlString = MvcHtmlString.Create("Hello,World!"); } <h3>@mvcHtmlString.ToHtmlString()</h3>
运行一下,查看网页源码如下:
<!DOCTYPE html> <html> <head> <title>这是默认的视图标题</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script> </head> <body> <h2>这是一个默认的原始视图!</h2> <h3>Hello,World!</h3> </body> </html>
从定义看到,MvcHtmlString的静态方法Create接受了一个常规字符串string型的参数,处理完成后返回了一个MvcHtmlString类型的实例:
namespace System.Web.Mvc { // 摘要: // Represents an HTML-encoded string that should not be encoded again. public sealed class MvcHtmlString : HtmlString { // 摘要: // Creates an HTML-encoded string using the specified text value. // // 参数: // value: // The value of the string to create . // // 返回结果: // An HTML-encoded string. public static MvcHtmlString Create(string value); } }
而且可以借助父类的ToHtmlString方法将MvcHtmlString转化成用于显示的常规string:
namespace System.Web { // 摘要: // 表示不应再次进行编码的 HTML 编码的字符串。 public class HtmlString : IHtmlString { // 摘要: // 返回 HTML 编码的字符串。 // // 返回结果: // HTML 编码的字符串。 public string ToHtmlString(); } }
接下来我将视图代码中的ToHtmlString方法去掉,即:
@{ ViewBag.Title = "这是默认的视图标题"; } <h2>这是一个默认的原始视图!</h2> @{ var mvcHtmlString = MvcHtmlString.Create("Hello,World!"); } <h3>@mvcHtmlString</h3>
生成的源码还是:
<!DOCTYPE html> <html> <head> <title>这是默认的视图标题</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script> </head> <body> <h2>这是一个默认的原始视图!</h2> <h3>Hello,World!</h3> </body> </html>
@{ ViewBag.Title = "这是默认的视图标题"; } <h2>这是一个默认的原始视图!</h2> @{ var mvcHtmlString = MvcHtmlString.Create("Hello,World!"); } <h3>@mvcHtmlString</h3> @{ var mvcHtmlStringTextBox = MvcHtmlString.Create("<input type=\"text\" name=\"text1\" value=\"Hello World!\" />"); } @mvcHtmlStringTextBox.ToHtmlString() @mvcHtmlStringTextBox
返回的网页:
<!DOCTYPE html> <html> <head> <title>这是默认的视图标题</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script> </head> <body> <h2>这是一个默认的原始视图!</h2> <h3>Hello,World!</h3> <input type="text" name="text1" value="Hello World!" /> <br /> <input type="text" name="text1" value="Hello World!" /> </body> </html>
说明MvcHtmlString实例的ToHtmlString方法是将字符串显示出来,而如果网页中直接返回MvcHtmlString,那么如果遇到控件标签则会被解释成html控件。
@{ ViewBag.Title = "这是默认的视图标题"; } <h2>这是一个默认的原始视图!</h2> @{ var mvcHtmlString = MvcHtmlString.Create("Hello,World!"); } <h3>@mvcHtmlString</h3> @{ var mvcHtmlStringTextBox = MvcHtmlString.Create("<inpuat type=\"text2\" nae=\"text1\" value=\"Hello World!\" />"); } @mvcHtmlStringTextBox.ToHtmlString() <br /> @mvcHtmlStringTextBox
运行:
<!DOCTYPE html> <html> <head> <title>这是默认的视图标题</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script> </head> <body> <h2>这是一个默认的原始视图!</h2> <h3>Hello,World!</h3> <inpuat type="text2" nae="text1" value="Hello World!" /> <br /> <inpuat type="text2" nae="text1" value="Hello World!" /> </body> </html>
可以看到,如果输错标签,那么网页上就不会出现对应的控件。应该是浏览器解析不了吧,什么都不会显示出来。
@{ ViewBag.Title = "这是默认的视图标题"; } <h2>这是一个默认的原始视图!</h2> @{ var mvcHtmlString = MvcHtmlString.Create("Hello,World!"); } <h3>@mvcHtmlString</h3> @{ var mvcHtmlStringTextBox = MvcHtmlString.Create("<input type=\"12345abc\" nae=\"text1\" value=\"Hello World!\" />"); } @mvcHtmlStringTextBox.ToHtmlString() <br /> @mvcHtmlStringTextBox
结果居然是:
可见浏览器解析时将不确定的type类型直接默认成text。
@{ ViewBag.Title = "这是默认的视图标题"; } <h2>这是一个默认的原始视图!</h2> @{ var mvcHtmlStringInstance=new MvcHtmlString("<input type=\"text\" name=\"text2\" value=\"Merry Christmas!\" />"); } @mvcHtmlStringInstance
对应的源码:
<!DOCTYPE html> <html> <head> <title>这是默认的视图标题</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script> </head> <body> <h2>这是一个默认的原始视图!</h2> <input type="text" name="text2" value="Merry Christmas!" /> </body> </html>
也可以将MvcHtmlString保存在集合中,利用特殊形式显示出来(这里使用遍历),如
@{ ViewBag.Title = "MvcHtmlString"; } <h2>这是一个MvcHtmlString使用示例!</h2> @{ var mvcHtmlStringList = new List<MvcHtmlString>() { new MvcHtmlString("<input type=\"text\" name=\"text1\" value=\"Merry Christmas!\" /> <br />"), new MvcHtmlString("<input type=\"text\" name=\"text2\" value=\"Merry Christmas!\" /><br />"), new MvcHtmlString("<input type=\"text\" name=\"text3\" value=\"Merry Christmas!\" /><br />"), new MvcHtmlString("<input type=\"text\" name=\"text4\" value=\"Merry Christmas!\" /><br />") }; } @foreach (var item in mvcHtmlStringList) { @item }
显示:
源码:
<!DOCTYPE html> <html> <head> <title>MvcHtmlString</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script> </head> <body> <h2>这是一个MvcHtmlString使用示例!</h2> <input type="text" name="text1" value="Merry Christmas!" /> <br /><input type="text" name="text2" value="Merry Christmas!" /><br /><input type="text" name="text3" value="Merry Christmas!" /><br /><input type="text" name="text4" value="Merry Christmas!" /><br /> </body> </html>
认识TagBuilder
这个类用于创建HTML元素,就是类似上面的:
<input type=\"text\" name=\"text1\" value=\"Merry Christmas!\" /> <br />
上面是手工敲的HTML元素,使用TagBuilder只不过是用另一种形式进行HTML元素的编写。
如:
@{ ViewBag.Title = "TagBuilder"; } <h2>这是一个TagBuilder使用示例!</h2> @{ var tagbulider = new TagBuilder("input"); tagbulider.Attributes.Add("type", "text"); tagbulider.Attributes.Add("name", "text1"); tagbulider.Attributes.Add("value", "Hello,world~"); tagbulider.GenerateId("id1"); var mvchtmlString = MvcHtmlString.Create(tagbulider.ToString(TagRenderMode.SelfClosing)); } @mvchtmlString
生成的网页元素是:
<!DOCTYPE html> <html> <head> <title>TagBuilder</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script> </head> <body> <h2>这是一个TagBuilder使用示例!</h2> <input id="id1" name="text1" type="text" value="Hello,world~" /> </body> </html>
以上是简单的TagBuilder示例,有关它的详细说明见这里
扩展HtmlHelper类
下面记录一下如何扩展HtmlHelper类,首先在项目下新建一个文件夹“MyManagers”,在文件夹里新建一个类“MyExternMethods.cs”
public static MvcHtmlString MyInput(this HtmlHelper htmlhelper, string name) { TagBuilder tag = new TagBuilder("input"); tag.Attributes.Add("type", "text"); tag.Attributes.Add("name", name); tag.Attributes.Add("value", "Hello,world~"); tag.GenerateId("id1"); return MvcHtmlString.Create(tag.ToString(TagRenderMode.SelfClosing)); }
然后,在Index视图文件文件中将代码修改为:
@using HtmlSampleApp.MyManagers; @{ ViewBag.Title = "HtmlHelper扩展方法示例"; } <h2>这是一个HtmlHelper扩展方法示例!</h2> @{ @Html.MyInput("myname"); }
编译运行,可以看到网页源码为:
<!DOCTYPE html> <html> <head> <title>HtmlHelper扩展方法示例</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script> </head> <body> <h2>这是一个HtmlHelper扩展方法示例!</h2> <input id="id1" name="myname" type="text" value="Hello,world~" /> </body> </html>
然后再新建另一个扩展方法,支持lambda表达式:
public static MvcHtmlString AnotherInput<TModel, TResult>(this HtmlHelper<TModel> htmlhelper, Expression<Func<TModel, TResult>> expression) { var property = expression.Body as MemberExpression; TagBuilder tag = new TagBuilder("input"); tag.Attributes.Add("type", "text"); tag.Attributes.Add("name", property.ToString()); tag.Attributes.Add("value", "Merry Christmas~"); tag.GenerateId("id1"); return MvcHtmlString.Create(tag.ToString(TagRenderMode.SelfClosing)); }
@using HtmlSampleApp.MyManagers; @model HtmlSampleApp.Models.Sheep @{ ViewBag.Title = "Index"; } <h2>Index</h2> @{ @Html.AnotherInput(m => m.name); }
编译运行,查看源码:
<!DOCTYPE html> <html> <head> <title>Index</title> <link href="/Content/Site.css" rel="stylesheet" type="text/css" /> <script src="/Scripts/jquery-1.7.1.min.js" type="text/javascript"></script> </head> <body> <h2>Index</h2> <input id="id1" name="m.name" type="text" value="Merry Christmas~" /> </body> </html>
看到,name的属性值就是lambda表达式的参数表达式(而不是表达式的值)。如果需要表达式的值,估计要使用反射,这里我还不清楚如何用。