摘自小牛之路
自定义 Helper Method 模板
前面我们简要介绍了 Helper Method 模板根据 Model 元数据生成 Html 元素的便捷之处。但有时候MVC提供的模板并不能满足我们的需求,这时我们可以为 Model 对象的某个属性自定义一个 Helper Method 模板。
在前文中我们知道,使用 Html.DropDownList(For) 可以为我们创建一个下拉列表,但这个方法有一点不好使,每次使用都需要给它构造器的第二个参数指定数据源,很是不方便。对于频繁使用的下拉列表,我们可以把它做成模板。下面我将通过为 Role 枚举类型(前文有定义)做一个下拉列表模板来演示如何自定义。
按照约定,MVC框架会在 /Views/Shared/EditorTemplates 文件夹下查找自定义的模板。因此我们需要先添加一个EditorTemplates 文件夹,然后在该文件夹下添加一个 Role.cshtml 文件,代码如下:
@model MvcApplication1.Models.Role @Html.DropDownListFor(m => m, new SelectList(Enum.GetNames(Model.GetType()), Model.ToString()))
这样就做好了一个模板,我们可以像下面这样在一个View中使用它:
@model MvcApplication1.Models.Person @Html.EditorFor(m => m.Role)
除了 EditorFor,调用任何一个模板化的Helper Method 为 Role 类型的属性呈现元素时都会显示为一个下拉列表,效果如下:
为了让这个功能更通用,使所有枚举类型都可以显示为这样的下拉列表,我们再改造一下这个功能。
删除原来的 Role.cshtml 文件,在同一目录下再新建一个 Enum.cshtml 分部视图,代码参考如下:
@model Enum @Html.DropDownListFor(m => m, Enum.GetValues(Model.GetType()).Cast<Enum>() .Select(m => { string enumVal = Enum.GetName(Model.GetType(), m); return new SelectListItem() { Selected = (Model.ToString() == enumVal), Text = enumVal, Value = enumVal }; }) )
然后我们可以在 Model 中通过 UIHint 特性来应用它,如下:
public class Person { public int PersonId { get; set; } ... [UIHint("Enum")] public Role Role { get; set; } }
再运行程序看到的效果是和上面一样的。
注意,MVC 是根据属性的类型在 /Views/Shared/EditorTemplates 目录下找自定义的模板的,所以一定要保证模板的文件名和属性类型名一致(或用UIHint特性指定为模板的名称)。
另外,如果自定义的模板和内置的模板同名,MVC会使用自定义的。可以根据这个特点来用自定义的模板替换系统内置的。例如,如果在 EditorTemplates 文件夹下创建一个 Boolean.cshtml,当MVC要为 Boolean 类型的属性呈现 Html 元素时,它会使用自定义的 Boolean.cshtml 分部视图来呈现。