在这篇文章中,我们学习如何使用母版页在多个页面中创建统一布局。例如:我们想把当前web程序中所有数据都以两列的页面布局形式来设置显示。
我们可以使用母版面来设置所有页面中共有的数据内容,如:网站Logo、导航链接、广告条等。这样每个页面中都会自动显示这些在母版页中设置的内容。
这里我们学习如何创建一个新的母版页,并使用该母版页创建一个新页面。
一、创建母版面(原创:灰灰虫的家http://hi.baidu.com/grayworm)
下面我们创建一个具有两列显示的母版页,在解决方案管理器中的Views\Shared文件夹上右击,选对“Add”-“New Item”,在弹出的对话框中选择“MVC View Master Page”如图所示:
《图1》
我们可以在程序中创建多个母版页视图,每个母版页视图中可以定义不同的显示布局。
母版页看起来很像一个标准的ASP.NET MVC视图,不一样的是:母版页中包含一个或多个<asp:ContentPlaceHolder>标记。<asp:ContentPlaceHolder>标记用来指定可以被内容页面重写的区域。
比如下面的母版页中,定义了两列的布局,它包含两个<asp:ContentPlaceHolder>标记,每个<asp:ContentPlaceHolder>标记都代表一列
Listing 1 – Views\Shared\Site.master
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site.Master.cs" Inherits="MvcApplication1.Views.Shared.Main" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title></title>
<style type="text/css">
html
{
background-color:gray;
}
.column
{
float:left;
width:300px;
border:solid 1px black;
margin-right:10px;
padding:5px;
background-color:white;
min-height:500px;
}
</style>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<h1>My Website</h1>
<div class="column">
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
<div class="column">
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
</asp:ContentPlaceHolder>
</div>
</body>
</html>
在上面的母版页视图中包含两个<div>标签,分别对应两列布局。在母版页的head标记中定义的.column样式表应用到两个div标记上。我们可点击下面“设计”标签切换到预览界面查看设计效果
《图2》
二、创建内容页面视图
当我们创建完母版页视图后,我们可以根据此母版页创建一个或多个内容页面视图。例如:我们可以这样为Home控制器创建一个Index页面视图。在解决方案管理器中右击Views\Home文件夹,选择“Add”-“New Item”,在弹出的对话框中选择MVC View Content Page模板,在name文本框中填入Index.aspx,再单击“Add”按钮。
《图3》
当点击“Add”按钮后会弹出一个对话框,让我们选择一个母版页视图来格式化当页的内容页面,如下图所示,我们可以在这个对话框中找到我们刚才创建的母版页,然后点击“OK”。
《图4》
当我们根据Site.master母版页创建了一个内容页面后,我们可以看到内容页面的代码,如下所示
Listing 2 – Views\Home\Index.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder2" runat="server">
</asp:Content>
在上面的代码中我们看到这个页面视图中包含了好多的<asp:Content>标记,每个<asp:Content>标记对应母版页中的<asp:ContentPlaceHolder>标记。在每个<asp:Content>标记中包含一个ContentPlaceHolderID属性,它代表该<asp:Content>标记的内容对应于母版页中那个<asp:ContentPlaceHolder>标记显示。
另外,大家还可以看到在我们上面内容页面中的代码中并不包含任何HTML标记(<html></html><head></head>等),因为所有的这些标记都在母版页中已经存在了,所以不需要在内容页面中再出现。
在内空页面中,我们的HTML和代码内容必须写在<asp:Content>标记对之内,如果在<asp:Content>标记对之外的话,当我们试图运行内容页面时会产生错误。
我们并不需要在内容页面中重写母版页中所有的<asp:ContentPlaceHolder>标记,我们只需要重写我们想要替换的<asp:ContentPlaceHolder>标记就可以了。
例如,我们在Index视图中只包含了两个<asp:Content>标记,每个<asp:Content>标记中都写了一些文字。
Listing 3 – Views\Home\Index.aspx (modified)
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<h1>Content in first column!</h1>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="ContentPlaceHolder2" runat="server">
<h1>Content in second column!</h1>
</asp:Content>
当我们运行Index视图时,它显示界面如下,这个界面包含了两列。此时内容页面把母版页的内容也给整合进来了。
《图4》
三、修改母版页的内容。(原创:灰灰虫的家http://hi.baidu.com/grayworm)
当我们在运行不同的内容页面时,要求母版面的内容也会根据不同的内容页面发生不的变化时,如何做呢?比如,我们想让每个不同的内容页面都有一个自己的标题(窗口标题栏中的文字),但标题栏的内容是在母版页中指定的,那我们如何为该母版页下的每个页面设置不同的标题呢?
有两种途径来解决我们的这个问题:
第一种法是我们在<%@ Page %>声明指示符中为内容页面视图声明Title属性。比如我们想把Index页面的标题设为“Super Great Website”,那我们可以把Index页面的声明指示符做如下声明。
<%@ page title="Super Great Website" language="C#" masterpagefile="~/Views/Shared/Site.Master" autoeventwireup="true" codebehind="Index.aspx.cs" inherits="MvcApplication1.Views.Home.Index"%>
当Index视图运行呈现在浏览器中的时候,它的标题就会显示在标题栏中,如下图所示。
《图5》
这里有很重要的一点需要大家注意:要想让上面的声明指示符能够正确执行,那我们在母版页中必须以<head runat=”server”>替代传统的<head>标记,如果<head>标记中没有包含runat=”server”属性的话,那我们内容页面<%@ Page title="Super Great Website" %>的标题就不会显示出来,默认情况下,母版页中的<head>标记是带有runat=”server”这个属性的。
另一个方法是我们在母版页中把需要在内容页面中修改的部份预先定义成<asp:ContentPlaceHolder>标记。比如,我们想要在内容页面中修改母版页中的标题 和meta标记,那我们在母版页的<head>标记中加入一个<asp:ContentPlaceHolder>标记。代码如下图所示:
Listing 4 – Views\Shared\Site2.master
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="Site2.Master.cs" Inherits="MvcApplication1.Views.Shared.Site2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<asp:ContentPlaceHolder ID="head" runat="server">
<title>Please change my title</title>
<meta name="description" content="Please provide a description" />
<meta name="keywords" content="keyword1,keyword2" />
</asp:ContentPlaceHolder>
</head>
<body>
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</body>
</html>
我们可以看到在上面的<asp:ContentPlaceHolder>标记中有默认的内容,如果我们在内容页面中不重写这个<asp:ContentPlaceHolder>标记,那当内容页面运行的时候会显示这些默认的内容。
下面的代码中,我们重写了母版页<head>标记中的<asp:ContentPlaceHolder>标记,并显示了自定义的标题和meta信息。
Listing 5 – Views\Home\Index2.aspx
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site2.Master" AutoEventWireup="true" CodeBehind="Index2.aspx.cs" Inherits="MvcApplication1.Views.Home.Index2" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
<title>The Index2 Page</title>
<meta name="description" content="Description of Index2 page" />
<meta name="keywords" content="asp.net,mvc,cool,groovy" />
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
Just some content in the body of the page.
</asp:Content>
总结:
在这篇文章中我们介绍了母版页和内容页面的一些基本的使用,我们学会了新建母版页和根据此母版页新建内容页面。然后我们又探讨了如何在不同的内容页面中修改母版面的显示信息。