主要讲解页面布局中的一些知识
@RenderBody()
@section
@Html.Partial(“GetName”)
@Html.Action(“Time”)
一、公共模板
1、@RenderBody()
在网站公用部分通过一个占位符@RenderBody()来为网站独立部分预留一个位置。然后私有页面顶部通过@{Layout=”公用模板路径”}来引入公用模板,并在自身放到公用模板的位置。同时也可以设置ViewData或ViewBag设置网站标题,关键词等信息。
@{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "从这里可以设置网站标题";
}
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
</head>
<body>
<div>下面是页面私有部分</div>
@RenderBody()
</body>
</html>
这样引入了公用的页面其它部分,同时还设置了标题。
二、section-节
节:@section
通过在页面中加入节可以设置多个公用模板部分,
@RenderSection(“Footer”) 定义一个节,当视图不提供这个节的代码时会报错:节未定义:“xxxxxx”。
@RenderSection(“Footer”,false) 重载,如果设置了第二个参数为false,则说明这个节不是必须的,当视图不提供这个节的代码时也不会报错。
我们还可以通过 IsSectionDefined 方法来判断一个section是否被定义或在当前View中是否能调用得到,如:
...
@if (IsSectionDefined("Footer")) {
@RenderSection("Footer")
} else {
<h4>This is the default footer</h4>
}
...
Razor视图引擎支持将View中的一部分内容分离出来,以便在需要的地方重复利用,减少了代码的冗余。下面来演示如何使用Section。
创建一个MVC应用程序,选择基本模板。添加一个HomeController,编辑生成的Index方法如下:
public ActionResult Index() {
string[] names = { "Apple", "Orange", "Pear" };
return View(names);
}
右击Index方法,添加视图,编辑该视图如下:
@model string[]
@{
ViewBag.Title = "Index";
}
@section Header {
<div class="view">
@foreach (string str in new [] {"Home", "List", "Edit"}) {
@Html.ActionLink(str, str, null, new { style = "margin: 5px" })
}
</div>
}
<div class="view">
This is a list of fruit names:
@foreach (string name in Model) {
<span><b>@name</b></span>
}
</div>
@section Footer {
<div class="view">
This is the footer
</div>
}
我们通过@section标签加section的名称来定义一个Section,这里创建了两个section:Header 和 Footer,习惯上一般把section放在View文件的开头或结尾以方便阅读。下面我们在 /Views/Shared/_Layout.cshtml 文件中来使用它们。
编辑 /Views/Shared/_Layout.cshtml 文件如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<style type="text/css">
div.layout { background-color: lightgray;}
div.view { border: thin solid black; margin: 10px 0;}
</style>
<title>@ViewBag.Title</title>
</head>
<body>
@RenderSection("Header")
<div class="layout">
This is part of the layout
</div>
@RenderBody()
<div class="layout">
This is part of the layout
</div>
@RenderSection("Footer")
<div class="layout">
This is part of the layout
</div>
</body>
</html>
当页面多个页面都使用到了同一个布局时,每个页面都要通过Layout属性来指定它的布局,会造成冗余,_ViewStart.cshtml(此文件本身已存在)可以用来消除这种冗余,在Views目录下又一个_ViewStart.cshtml文件,这个文件优先于同目录下任何视图的执行,可以用它来指定一个默认布局。
@{
Layout = “~/Views/Shared/_Layout.cshtml”;
}
这样所有的视图都会将此布局作为默认布局,如果有视图不想要此布局,可以在视图中重写Layout属性。如果不想要布局,则设置Layout=”“即可。
三、分部视图
分部视图顾名思义是一个视图的一部分,它允许程序员将视图中的一部分独立出来,在某些需要的页面引用。能够减少代码重复,提高页面代码重用性。
例如:下面这个是返回一个分部视图的Action
public ActionResult GetName()
{
return PartialView();
}
在其它任意视图中,只要写如下代码:
@Html.Partial("GetName")
//或者可以写成这样
@{
Html.RenderPartial("GetName");
}
就能够在页面中加载GetName视图的完整代码了。一般来说,分部视图当中不应该包括js,或css因为这样,等于在大视图中到处都是分部视图的JS与CSS了,一个好的做法是私有JS与CSS通过一个节来引入,这样比较好。都是最好也不要有里面的内容,以及标签。因为如果有了这些,还不如搞成布局呢。分部视图这个东西最有用的地方在于能够把页面中共同的部分提取出来,在用的时候简单引入就行,而实际上,分部视图除了不能指定布局之外,几乎跟普通视图一样,很爽的一个东西。引用视图可以通过:
@Html.Partial("分部视图名称") //有或者下面三行
@{
Html.RenderPartial("分部视图名称");
}
另外分部视图中要注意@Html.Partial()中的重载,这些重载常常有用,如果实在欠缺,就自己写扩展方法来实现。来看看这些重载方法的方法签名。
public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName);
public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName, object model);
public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName, ViewDataDictionary viewData);
public static MvcHtmlString Partial(this HtmlHelper htmlHelper, string partialViewName, object model, ViewDataDictionary viewData);
由方法签名中可以看出来,这些都是扩展方法,@Html.Partial是可以将数据实体和数据字典给分部视图的,然后分部视图那边可以通过主视图传过去的数据再生成视图。
给个例子:传递一个Model过去分部视图,然后分部视图那边根据传入的数据再解释视图。来看Controller代码
namespace MvcStart.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
Man_Model man = new Man_Model();
man.Id = 1;
man.Name = "张飞";
man.Age = 23;
return View(man);
}
public ActionResult getName(object o)
{
Man_Model man = o as Man_Model;
return PartialView(man);
}
}
public class Man_Model
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
视图代码:Index.cshtml
@model MvcStart.Controllers.Man_Model
@Model.Id
@Model.Age
@Html.Partial("getName",Model);
getName.cshtml
@model MvcStart.Controllers.Man_Model
<div style="background-color:red">@Model.Name</div>
生成的HTML代码为:
<html>
<head>
<title>Index</title>
</head>
<body>
1 23
<div style="background-color:red">张飞</div>
</body>
</html>
再来记录一个技巧,例如一个网站在调试的时候用的是一个测试路径,上传之后用的是真正的域名,这个时候我们可以将域名写在配置文件或XML文件里,运行是读取,这时候我们可以定义一个静态属性,该属性返回真正的域名。在所有的视图中都可以@命名空间.类.静态变量 获得真正的域名。也就是说,在视图中一些小的可变化片段都可以这样来获取。
另外,特别需要注意Html.RenderAction()之类的方法还支持传入参数,具体方式如下:
@Html.RenderAction(“Left_Nav”, “Nav”, new{ ParentId = 3 });
跨区域调用的方式:
@{ Html.RenderAction(“Datagrid”, “DataList”, new { area = “Common” }); }
在Action里面直接加个参数ActionResult(int ParentId)就能够取得参数值。area会被MVC所截取,分析为跨区域调用。
区别:
Partial 分部视图
另外还有Html.RenderPartial和Html.RenderAction,都是用于在模板页中显示一个功能相对独立的块。
Partial与RenderPartial的相同点
两者都用于获取一个分部视图。
Partial与RenderPartial的区别
1. Partial有返回值(MvcHtmlString);RenderPartial没有返回值(Void)。
有返回值可以@Html.Partial()
而没有返回值就直接@{ Html.Partial(); }
Partial返回字符串,因此你可以用一个变量来接收返回的Html字符串。但是RenderPartial是将结果写入到Response中,因此没有办法用变量来接收。
以上两种写法等价。
Action与RenderAction的区别
都用于引入一个Action的代码,其区别与上面Partial和RenderPartial的区别相同
两者的相同点
RenderPartial和RenderAction通常都被用来显示一个功能相对独立的“块”,比如说显示菜单或者导航条。 两者输出的结果都被作为调用的View的一部分显示。
两者的不同点
RenderPatial的数据来自于调用的View,而RenderAction来自自己。
RenderAction会发起一个新的Request,而RenderPatial不会。
RenderPartial方法是return PartialView();而RenderAction是return View()。
四.Child Action
Child action 和 Patial view 类似,也是在应用程序的不同地方可以重复利用相同的子内容。不同的是,它是通过调用 controller 中的 action 方法来呈现子内容的,并且一般包含了业务的处理。任何 action 都可以作为子 action 。接下来介绍如何使用它。
在 HomeController 中添加一个 action,如下:
[ChildActionOnly]
public ActionResult Time()
{
return PartialView(DateTime.Now);
}
这个 action 通过调用 PartialView 方法来返回一个 partial view。ChildActionOnly 特性保证了该 action 只能作为子action被调用(不是必须的)。
接着我们继续为这个action添加一个相应的 Time.cshtml 视图,代码如下:
@model DateTime
<p>The time is: @Model.ToShortTimeString()</p>
在 List.cshtml 视图中添加如下代码来调用 Time action 方法 :
...
@Html.Action("Time")
我们通过 @Html.Action 方法来调用了 Time action 方法来呈现子内容。在这个方法中我们只传了一个action名称参数,MVC将根据当前View所在Controller去查找这个action。如果是调用其它 controller 中的 action 方法,则需要在第二个参数中指定 controller 的名称,如下:
@Html.Action("Time", "MyController")
该方法也可以给 action 方法的参数传值,如对于下面带有参数的 action:
...
[ChildActionOnly]
public ActionResult Time(DateTime time) {
return PartialView(time);
}
…
我们可以这样使用 @Html.Action 方法:
…
@Html.Action(“Time”, new { time = DateTime.Now })