风影ASP.NET基础教学16 母版页
在以往我们做所有操作,都必须独立的使用页面,如果要有相同的部分内容的话,我们可以通过iframe,frameset这两种html的框架来达到目的。但是使用起来远没有我们要说的这个母版页灵活.
创建母版页
新建项里我们选择母版页。
我们开看一下母版页的内容
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="MyMaster.master.cs" Inherits="MasterDemo.MyMaster" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
我们看到我们常见到了Page指令被换成了@Master指令,@Master指令与@Page指令类似。我们还发现默认的母版页有两个ContentPlaceHolder控件。第一个被定义在了head标记内,一个定义在body中form中。若要创建更加复杂的布局则需要自己手动添加其他标记和ContentPlaceHolder控件。
Master与Page的区别
- 窗体都是以aspx文件后缀。母版页是master
- 窗体以@Page指令开头,母版页是@Master
- 母版页可以使用ContentPlaceHolder控件。窗体不能。
- 母版页不能直接运行,需要内容页。
自定义母版页
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="MyMaster.master.cs" Inherits="MasterDemo.MyMaster" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<header >
<asp:ContentPlaceHolder ID="Header" runat="server">
</asp:ContentPlaceHolder>
</header>
<aside>
</aside>
<asp:ContentPlaceHolder ID="Main" runat="server">
</asp:ContentPlaceHolder>
</form>
</body>
</html>
由此可见我们可以随意更改模板页面的布局。
我们若是要使用这个母版页则需要创建使用母版页的内容页
并选择对应的母版页
<%@ Page Title="" Language="C#" MasterPageFile="~/MyMaster.Master" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="MasterDemo.WebForm1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="Header" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Main" runat="server">
</asp:Content>
对应的内容页面我们可以看到其实就是我们常用的普通页面只是这个页面更为干净整洁。
在@Page指令上我们发现了MasterPageFile属性。它指定了绑定的母版页的路径。并且在代码中出现了两个Content控件。通过ContentPlaceHolderID属性我们可以看到和之前母版页的ContentPlaceHolder属性是一一对应的。也就是说这个内容页面的内容将会和母版页的内容组合成一个全新的页面。作为一个整体显示出来。
<%@ Page Title="" Language="C#" MasterPageFile="~/MyMaster.Master" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="MasterDemo.WebForm1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="Header" runat="server">
<asp:Button ID="Button1" runat="server" BackColor="Red" Text="Header" />
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Main" runat="server">
<asp:Button ID="Button2" runat="server" BackColor="Red" Text="Main" />
</asp:Content>
显示效果
设置页面标题
母版页可以设置默认的标题内容,但是这样我们的需求要远比这个多得多。毕竟我们每个内容页的标题都不可能是一样的,这样我们就可以通过Page的Title属性,来进行自定义设置。
页面事件发生的顺序
- ASP.NET创建模板页面控件
- 添加内容页的子控件
- 触发母版页的Page.Init事件
- 内容页的Page.Init事件
对于Page.Load事件,可以执行相同的步骤。如果有冲突,在内容页进行自定义如修改页面标题。
ContentPlaceHolder控件里的默认内容
<%@ Master Language="C#" AutoEventWireup="true" CodeBehind="DefaultContentPlaceMaster.master.cs" Inherits="MasterDemo.DefaultContentPlaceMaster" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder ID="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
<h1>这是默认内容</h1>
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
内容页
<%@ Page Title="" Language="C#" MasterPageFile="~/DefaultContentPlaceMaster.Master" AutoEventWireup="true" CodeBehind="DefaultContent.aspx.cs" Inherits="MasterDemo.DefaultContent" %>
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
要使用默认内容很简单,则需要把内容页面对应的Content控件删除即可
相对路径处理
通常情况下,我们会把所有的模版页和内容页进行归类划分,微软也提倡这种做法。
只是这样做的话,我们的资源路径会有一些少许的不同
<body>
<form id="form1" runat="server">
<div>
<asp:Image ID="Image1" runat="server" ImageUrl="1.jpg" Width="100" />
<img runat="server" src="2.jpg" id="img1" width="100" />
<img src="2.jpg" id="img2" />
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
我们发现用服务器控件时,通过母版页的相对路径可以获取正常的图片。但是普通的img不能正常显示。我们来分析一下生成的源码。
我们清楚的看到服务器控件会自动识别并转换对应的路径而普通的img控件则不能。
母版页和内容页之间传递数据
我们经常有一些属性和方法传递个内容页,我们常用的方案是在母版页中创建公开的属性。在内容页中可以通过Page.Master属性来获取对应的模板对象。这样就达到了内容页获取母版页内容的目的。
或者使用@MasterType指令的方式。
比如我们在母版页中添加了一个公开属性MyDemo。
内容页添加
<%@ MasterType VirtualPath="~/MasterPages/MasterPath.Master" %>
后置代码就可以直接使用了
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Master.MyDemo = "123";
}
}