阅读目录:

7.HtmlHelper、HtmlHelper<T>中的ViewModel的类型推断

8.控制ViewModel中的某个属性的呈现(使用PartialView部分视图细粒度控制ViewModel的呈现)

9.模板的装饰者模式(PartialView与ViewModel的嵌套使用(简))

7.HtmlHelper、HtmlHelper<T>中的ViewModel的类型推断

在View中用来根据当前View中引入的强类型ViewModel生成HTMLDom结构的核心功能都被封装在以HtmlHelper为首的对象模型中,包括HtmlHelper<T>泛型类型,它直接派生自HtmlHelper基类,这两个类型的功能都是围绕着如何生成前端所需要的HTML结构和一些常用的UI元素;

但是这两个类型所能做的事情很有限,它们只是庞大生成功能的核心模型;我们使用的都是围绕着这两个类型的扩展方法,如:

@Html.EditorForModel()

在当前View中引用的Html属性其实是一个HtmlHelper<T>类型的属性,定义代码:

public HtmlHelper<TModel> Html { get; set; }

该类型被定义在public abstract class WebViewPage<TModel> : WebViewPage类中,其实该类是一个模板化代码生成的基类;我们在ASP.NETMVC项目中添加的所有View文件都会直接或间接的继承自该类型,在View中引入的类型定义:

@model  MvcApplication4.Models.Customer

正是这里泛型类型的类型参数,所以围绕着HtmlHelper<T>的扩展方法才变成灵活的泛型的代码生成接口;因为他们彼此通过强大的泛型类型推断,依次的推断下去,最终会到达扩展方法的内部,如:

@Html.EditorFor(model => model.Shopping)

这意思是说在View中输出一个编辑model.Shopping属性的文本框HtmlDom结构,但是我们调用的明明是一个没有任何类型形参的方法,其实它已经通过上面说将的环节进行了类型关联;

画红线的部分是View所使用的强类型HtmlHelper<T>对象,类型参数是我们在View中通过@model的方式定义的;画绿色的部分也是强类型的EditorFor<T>方法,同样该泛型方法已经被类型推断过了,看泛型方法的定义:

public static class EditorExtensions
{
  public static MvcHtmlString EditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression);
}

上述代码中加粗的部分正是关键所在,这里扩展的其实是我们在View中引入的强类型参数的HtmlHelper<MvcApplication4.Models.Customer>,这样任何围绕HtmlHelper<T>进行扩展的扩展方法都会最终使用到类型ViewModel;

8.控制ViewModel中的某个属性的呈现(使用PartialView部分视图细粒度控制ViewModel呈现)

对于ViewModel的呈现一直都是被系统控制着,虽然一个简单的字符串类型字段可以用一个文本框的HtmlDom结构方式呈现出来,但是那仅仅是代表着没有任何业务概念的功能性设置,也就是出发点是从CLR类型系统考虑的,而不是特定领域角度;如果这个字符串代表着某种业务概念,那么我们希望通过更人性化的方式让用户使用,而不是一个硬生生的文本框;我们可能会需要提供了一个供自动输入提示的HtmlDom结构,该结构可能还需要其他的UI成员协助,如:自动提示可能需要JS、后台Service接口等一系列成员相互协调完成;

这是一个简单的需求,在大型项目中这样的功能很常见,也是到处会使用到,不单单是一个两个页面,N多页面都会有一点点的差异性,但是整体功能都会差不多,这样我们只需要在设计的时候适当的提供一些接口就可以了;

那么ASP.NETMVC是如何生成前台所需要的HtmlDom结构的呢? 前面一章我们总结了,对于ViewModel的呈现形式只会有两种,一种是Edit一种是Display,不会有其他的呈现形式,所以在围绕着HtmlHelper对象的扩展方法中大多数都是以这种类别区分的,Edit一组,Display一组;

到目前位置我们已经知道ViewModel与View之间的桥梁是Model元数据,可以简单的理解为HtmlHelper<T> 一系列扩展方法都是通过获取Model元数据信息来控制到底需要输出什么形式的HtmlDom结构,而Model元数据都是通过Model元数据控制特性来完成的,这就可以通过控制Model元数据来控制Model的呈现细节;

public class Address
{
[UIHint("CustomAddress")]
[Display(Name = "地址")]
public string AddressId { get; set; } }

我们在Address类型中为AddressId属性加上一个UIHint类型的特性,其实意思是想说明我们在程序内部使用的是使用地址ID,而在现实的时候我们希望将原来很单调的地址ID编程一个更人性化的地址显示方式,比如:位于什么省、什么市等等一些其他的地理信息;

在ASP.NETMVC内部有一个internal static class TemplateHelpers 类型的模板辅助类,该类是大部分模板化输出的帮助接口,在该类的内部定义了一套模板化使用的字典:

视图的类型:

static readonly Dictionary<DataBoundControlMode, string> modeViewPaths =
new Dictionary<DataBoundControlMode, string> {
{ DataBoundControlMode.ReadOnly, "DisplayTemplates" },
{ DataBoundControlMode.Edit, "EditorTemplates" }
};

这里定义了两组类型,也就是显示、编辑,这两组类型将作为查找自定义模板的物理文件夹路径,同样ModelMedata中的同一个属性在不同的显示类型中将有不同的判断作用;

编辑、显示:

static readonly Dictionary<string, Func<HtmlHelper, string>> defaultDisplayActions =
new Dictionary<string, Func<HtmlHelper, string>>(StringComparer.OrdinalIgnoreCase) {
{ "EmailAddress", DefaultDisplayTemplates.EmailAddressTemplate },
{ "HiddenInput", DefaultDisplayTemplates.HiddenInputTemplate },
{ "Html", DefaultDisplayTemplates.HtmlTemplate },
{ "Text", DefaultDisplayTemplates.StringTemplate },
{ "Url", DefaultDisplayTemplates.UrlTemplate },
{ "Collection", DefaultDisplayTemplates.CollectionTemplate },
{ typeof(bool).Name, DefaultDisplayTemplates.BooleanTemplate },
{ typeof(decimal).Name, DefaultDisplayTemplates.DecimalTemplate },
{ typeof(string).Name, DefaultDisplayTemplates.StringTemplate },
{ typeof(object).Name, DefaultDisplayTemplates.ObjectTemplate },
}; static readonly Dictionary<string, Func<HtmlHelper, string>> defaultEditorActions =
new Dictionary<string, Func<HtmlHelper, string>>(StringComparer.OrdinalIgnoreCase) {
{ "HiddenInput", DefaultEditorTemplates.HiddenInputTemplate },
{ "MultilineText", DefaultEditorTemplates.MultilineTextTemplate },
{ "Password", DefaultEditorTemplates.PasswordTemplate },
{ "Text", DefaultEditorTemplates.StringTemplate },
{ "Collection", DefaultEditorTemplates.CollectionTemplate },
{ typeof(bool).Name, DefaultEditorTemplates.BooleanTemplate },
{ typeof(decimal).Name, DefaultEditorTemplates.DecimalTemplate },
{ typeof(string).Name, DefaultEditorTemplates.StringTemplate },
{ typeof(object).Name, DefaultEditorTemplates.ObjectTemplate },
};

这是两组显示模式的模板化操作方法的字典,可以看出同一个HiddenInput特性将在不同的显示模式先输出不同的HtmlDom结构;

在我们的ASP.NETMVC项目中要同样的有两组文件夹DisplayTemplates、EditorTemplates,这两个文件夹将会是系统查找的路径;

我们在DisplayTemplates目录下创建了一个用来显示客户地址信息的自定义模板,其实也就是PartialView部分视图,用来重用UI;在该部分视图中,我们写点测试数据:

@model string 

<div>
<h2>@Model</h2>
<h2>地址:上海市、长宁区</h2>
<h2>气温:-1~10</h2>
<h2>交通:方便出行</h2>
</div>

然后我们刷新一下界面,看如何个性化了地址显示;

这样我们就可以控制细粒度的ViewModel显示;

9.模板的装饰者模式(PartialView与ViewModel的嵌套使用(简))

其实我们应该能够领悟到通过PartialView与HtmlHelper彼此互相嵌套能让原本单一的部分视图变成一个强大的具有设计模式功能的模板装饰者模式;想想看,如果我们将这里的AddressId类型再设计成复杂的类型,然后在该复杂的类型内部我们嵌套了一个原本在其他地方使用的地址类型ViewModel,而且刚好该类型也具有相应的部分是视图,这样我们就可以将ViewModel的嵌套使用与PartialView嵌套使用相结合,这样就可以使用类似设计模式中的装饰者模式来完成很多UI上的展现重用功能;

作者:王清培

出处:http://www.cnblogs.com/wangiqngpei557/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面

.NET/ASP.NETMVC 深入剖析 Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(三)的更多相关文章

  1. .NET/ASP.NETMVC Model元数据、HtmlHelper、自定义模板、模板的装饰者模式(一)

    .NET/ASP.NETMVC Model元数据.HtmlHelper.自定义模板.模板的装饰者模式(一) 阅读目录: 1.开篇介绍 2.Model与View的使用关系(数据上下文DataContex ...

  2. MVC中Model元数据及绑定机制

    ASP.NET MVC的Model为View Model,表示最终呈现在View上的数据,而Model元数据的一个重要的作用在于控制对象在View上的呈现方式.说得更加具体点,就是基于某种数据类型的M ...

  3. MVC之Model元数据

    Contronoller激活之后,ASP.NET MVC会根据当前请求上下文得到目标Action的名称,然后解析出对应的方法并执行之. 在整个Action方法的执行过程中,Model元数据的解析是一个 ...

  4. .NET/ASP.NETMVC 大型站点架构设计—迁移Model元数据设置项(自定义元数据提供程序)

    阅读目录: 1.需求背景介绍(Model元数据设置项应该与View绑定而非ViewModel) 1.1.确定问题域范围(可以使用DSL管理问题域前提是锁定领域模型) 2.迁移ViewModel设置到外 ...

  5. 【笔记】ASP.NET MVC Model元数据

    问题1:什么叫Model元数据? Model元数据,是针对数据类型的一种描述信息.由于复杂类型(或者说类型嵌套的存在,比如CustomerModel中有一个属性为复杂类型Address)的存在,因此M ...

  6. ASP.NET MVC Model元数据(五)

    ASP.NET MVC Model元数据(五) 前言 在上一篇中我们描述了应用于Model上面的各种用于显示控制的特性类,在本篇中将详细的介绍这些特性类的应用,虽然它们跟Model元数据的直接关系并不 ...

  7. ASP.NET MVC Model元数据(四)

    ASP.NET MVC Model元数据(四) 前言 前面的篇幅讲解了Model元数据生成的过程,并没有对Model元数据生成过程的内部和Model元数据结构的详细解释.看完本篇后将会对Model元数 ...

  8. ASP.NET MVC Model元数据(三)

    ASP.NET MVC Model元数据(三) 前言 在上篇中我们大概的讲解了Model元数据的生成过程,并没有对Model元数据本身和详细的生成过程有所描述,本篇将会对详细的生成过程进行讲解,并且会 ...

  9. ASP.NET MVC Model元数据(二)

    ASP.NET MVC Model元数据(二) 前言 在上篇中,给大家留个对Model元数据的印象,并没有对Model元数据有过多的讲解,而在本篇中也不会对Model元数据的本身来解释,而是针对于它的 ...

随机推荐

  1. ZOJ Problem Set - 1337 Pi 最大公约数

    这道题目的关键在于怎么求两个整数的最大公约数,这里正好复习一下以前的知识,如下: 1.设整数a和b 2.如果a和b都为0,则二者的最大公约数不存在 3.如果a或b等于0,则二者的最大公约数为非0的一个 ...

  2. 1Z0-053 争议题目解析24

    1Z0-053 争议题目解析24 考试科目:1Z0-053 题库版本:V13.02 题库中原题为: 24.Which of the following information will be gath ...

  3. 软件工程 Android小游戏 猜拳大战

    一.前言 最近学校举办的大学生程序设计竞赛,自己利用课余时间写了一个小游戏,最近一直在忙这个写这个小游戏,参加比赛,最终是老师说自己写的简单,可以做的更复杂的点的.加油 二.内容简介 自己玩过Andr ...

  4. (十二) WebGIS中矢量图层的设计

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 在前几章中我们已经了解了什么是矢量查询.屏幕坐标与地理坐标之 ...

  5. CSS-清除浮动

    什么是CSS清除浮动? 在非IE浏览器(如Firefox)下,当容器的高度为auto,且容器的内容中有浮动(float为left或right)的元素,在这种情况下,容器的高度不能自动伸长以适应内容的高 ...

  6. Design Patterns Simplified - Part 2 (Singleton)【设计模式简述--第二部分(单例模式)】

    原文链接: http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part-2-singleton/ De ...

  7. de4dot3.14更新文件打包下载

    刚发现de4dot更新了,虽然只是10月份的文件更新,并未发布新的release,但好多人还不会编译... 关于de4dot有何功能就不再讲了. 本文主要提供编译通过后的打包文件下载. 首先下载de4 ...

  8. JS 常用验证REG

    不错的JS验证~~~~~~~~~~~~~~~~~~~~~~~~~ 用途:校验ip地址的格式 输入:strIP:ip地址 返回:如果通过验证返回true,否则返回false: */ function i ...

  9. JAVA 链表操作:单链表和双链表

    主要讲述几点: 一.链表的简介 二.链表实现原理和必要性 三.单链表示例 四.双链表示例 一.链表的简介 链表是一种比较常用的数据结构,链表虽然保存比较复杂,但是在查询时候比较便捷,在多种计算机语言都 ...

  10. Oracle 数据库基础学习 (七) SQL语句综合练习

    一.多表查询综合练习 1.  列出高于在30部门工作的所有人员的薪金的员工的姓名.部门名称.部门编号.部门人数 分析: 需要的员工信息: |-emp表:姓名.部门编号 |-dept表:部门名称.部门编 ...