本篇最后两节没看懂,但是日子还是要过,先笔录下来等以后再慢慢理解吧。。。
视图的生存目标是取得一个送给它的模型并用这个模型来渲染内容。由于控制器及相关服务已经执行了所有业务逻辑并将结果包装成一个模型对象,故视图只需要知道如何取得这一模型并把它转换成HTML。
一、选择待渲染视图:
视图是通过控制器动作中调用View方法来渲染的,如前面所讲GuestbookController中的Create动作:
public ActionResult Create() { return View(); }
当不带参数调用View方法时,框架默认渲染视图的名字与动作名(Create)相同,默认的视图引擎会在Views/<控制器名>和Views/Shared目录中查找。
若要渲染的视图与动作名不同,则需要传参给View方法,如New.cshtml,则 return View("New")。如果视图不在与控制器同名的子目录中,则需要指定相关路径,如return View("~/Views/SomeOtherDirectory/New.cshtml")。
二、给视图传递数据:
将数据传递给视图有三种方式:ViewDataDictionary(视图数据字典)、ViewBag(视图包)和强类型视图。
1.ViewDataDictionary:
修改Details动作和Details视图,如下:
1 public ActionResult Details(int? id) 2 { 3 if (id == null) 4 { 5 return new HttpStatusCodeResult(HttpStatusCode.BadRequest); 6 } 7 GuestbookEntry guestbookentry = db.Entries.Find(id); 8 if (guestbookentry == null) 9 { 10 return HttpNotFound(); 11 } 12 bool IsShowEdit = guestbookentry.Name == "张无忌"; 13 ViewData["IsShowEdit"] = IsShowEdit; 14 return View(guestbookentry); 15 }
1 @* 以上省略 *@ 2 <p> 3 @{ 4 bool IsShowEdit = (bool)ViewData["IsShowEdit"]; 5 } 6 @if(IsShowEdit) 7 { 8 @Html.ActionLink("Edit", "Edit", new { id = Model.Id }) 9 } 10 @Html.ActionLink("Back to List", "Index") 11 </p>
我们可以在ViewDataDictionary中存储任何数据,但是从字典接收数据必须执行类型转换。
2.ViewBag:
上面的Details动作和Details视图可修改为:
ViewBag.IsShowEdit = IsShowEdit;
@if(ViewBag.IsShowEdit)
{
@Html.ActionLink("Edit", "Edit", new { id = Model.Id })
}
ViewBag不需要类型转换,可以直接使用。
ViewData和ViewBag的优点是灵活,缺点是如果在使用中输错动态属性名编译器不能检测出错误。另外也不能将元数据添加到动态属性上,如注解属性。
3.强类型视图:
使用@model关键字指定模型类型就得到了一个强类型,如Index视图中:
@model IEnumerable<Guestbook.Models.GuestbookEntry>
也可以写成:
@using Guestbook.Models @model IEnumerable<GuestbookEntry>
我们可以利用专为强类型视图设计的HtmlHelper扩展方法显示强类型视图数据,清单如下:
三、使用强类型模板:
HtmlHelper扩展方法适合于个别的HTML元素片段,但是当生成的HTML开始变得更加复杂并且包含各种元素时一般不倾向与扩大使用。MVC团队又设计了模板辅助器(Templated Helper),辅助生成基于强类型的HTML。
1.DisplayFor和EditorFor模板:
2.内建模板:
除Collection和Object模板外,每个模板都渲染一个单值。Collection模板循环遍历模型对象中的每个数据项,Object模板循环遍历ModelMetadata.Properties集合的每个数据项。
3.选择模板:[ 暂时没搞太懂。。。]
本质上显示模板和编辑模板的辅助器方法是使用一个特定的算法按照名称查找来选择所用的模板。
模板的搜索位置是DisplayTemplates和EditorTemplates文件夹,像部分视图和视图的名称一样,在转向Shared视图文件夹之前模板方法首先查看控制器(或“区域+控制器”)专用的视图文件夹。以编辑模板为例,如果模板辅助器方法是在区域专用视图中使用的那么这些文件夹包括:
如果在这些文件夹中没找到模板或者该视图不在区域中,将使用默认的视图搜索位置:
4.定制模板:[ 彻底没看懂,哭。。。]
建立在部分视图上的模型模板的优点:
1).部分视图需要在视图中通过名称来选择,模板是通过模型元数据信息来选择的,无须为视图明确指定使用哪个模板;
2).ViewDataDictionary给模板提供了额外信息,部分视图和其他页面是接收不到这些信息的,这种信息在ViewData.ModelMetadata属性中。
利用ModelMetadata属性可以访问通过模型元数据提供器(Model Metadata Provider)生成的所有元数据信息,包括模型类型信息、属性以及模型的元数据。
除了一般的模型类型信息外,ModelMetadata对象还包括其他元数据,这些默认是通过注解属性填充的。
ModelMetadata对象还公开了一个类型为IDictionary<string,object>的AdditionalValues属性,它能包含通过自定义模型元数据提供器填充的附加元数据信息。