14.4 嵌套母版页

通过上面几节对母版页和内容页的讲解,相信读者已经了解了母版页和内容页之间的关系了。其实,在实际应用中,可以使这种关系结构变得更复杂些,即一个母版页可以与另一个母版页关联,形成一种层次性的嵌套结构。也就是说,可以在一个母版页中包含另一个母版页,以此来完成页面构建工作。

但需要明确的是,无论如何嵌套母版页,它们都必须包含一个能够运行的内容页(其原因是,扩展名为.master的文件不能被浏览器所访问)。接下来,通过一个简单的示例来详细阐述如何嵌套母版页。

14.4.1 一个嵌套母版页示例

为了演示这种母版页的嵌套关系,先来创建第一个母版页。该母版页包含一个ContentPlaceHolder控件One,如代码清单14-8所示。</p>

代码清单14-8 SiteOne.Master


<%@Master Language="C#"AutoEventWireup="true"

CodeBehind="SiteOne.master.cs"

Inherits="_14_5.SiteOne"%>

<!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 runat="server">

<title></title>

</head>

<body>

<form id="form1"runat="server">

<div>

<div style="background-color:#cccccc;

height:30px">

<h1>

第一个母版页</h1>

</div>

<div>

<asp:Label ID="txt_one"runat="server"

Text="我是第一个母版页里的Label控件txt_one">

</asp:Label>

</div>

<div>**

**</div>

<asp:ContentPlaceHolder ID="One"

runat="server">

</asp:ContentPlaceHolder>

</div>

</form>

</body>

</html>


创建好第一个母板页SiteOne.Master后,就可以继续创建第二个使用该母版页(通过@Master指令的MasterPageFile属性)的母版页SiteTwo.Master了。SiteTwo.Master母版页可以从第一个母版页SiteOne.Master中获得相关的信息,并且还可以在本母版页中添加自己的信息和ContentPlaceHolder控件Two。值得注意的是,这些内容必须添加在Content控件内。示例如代码清单14-9所示。

代码清单14-9 SiteTwo.Master


<%@Master Language="C#"AutoEventWireup="true"

CodeBehind="SiteTwo.master.cs"

MasterPageFile="~/SiteOne.Master"

Inherits="_14_5.SiteTwo"%>

<asp:Content ID="Content1"ContentPlaceHolderID="One"

runat="server">

<div>

<div style="background-color:#cccccc;

height:30px">

<h1>

第一个母版页</h1>

</div>

<div>

<asp:Label ID="txt_two"runat="server"

Text="我是第二个母版页里的Label控件txt_two">

</asp:Label>

</div>

<div>**

**</div>

<asp:ContentPlaceHolder ID="Two"

runat="server">

</asp:ContentPlaceHolder>

</div>

</asp:Content>


在上面的代码中,其实不必向SiteTwo.Master母版页手动添加MasterPageFile属性。可以在创建SiteTwo.Master母版页时使用“选择母版页”复选框,这和在创建一个内容页面的方法一样。

创建好SiteTwo.Master母版页之后,就可以在内容页面里直接引用它了,如代码清单14-10所示。

代码清单14-10 Test.aspx


<%@Page Title=""Language="C#"

MasterPageFile="~/SiteTwo.Master"

AutoEventWireup="true"CodeBehind="Test.aspx.cs"

Inherits="_14_5.Test"%>

<asp:Content ID="Content1"ContentPlaceHolderID="Two"

runat="server">


在内容页面里面设置的内容。


</asp:Content>


运行代码清单14-10,结果将显示第一个母版页SiteOne.Master和第二个母版页SiteTwo.Master内容之和,如图14-11所示。

figure_0512_0398

图 14-11 嵌套母版页示例运行结果

在实际开发中,可以使用任意多级的嵌套母版页。不过,实现它们时一定要小心,虽然它听起来是模块化设计的好方法,但是它带给你的束缚比想象的要多。例如,如果以后决定网站的两个区域需要相似但稍微不同的标题,将不得不修改母版页的结构。因此,最好只使用一级母版页并复制少量的通用元素。大部分情况下,不会创建很多母版页,所以重复的代码不会很多。

14.4.2 嵌套母版页中的控件访问

前面已经讲过,如果一个内容页对应一个没有嵌套的母版页,那么就可以直接使用方法Master.FindControl来访问这个母版页上的所有控件。但对于嵌套多层的母版页来说,这种方法就不太适合了。

对于嵌套母版页中的控件访问,可以分为两种情况进行处理:

(1)对顶层母版页控件的访问

对顶层母版页控件的访问方法类似于对没有嵌套的母版页控件的访问。唯一不同的是:没有嵌套的母版页控件的访问只有一级Master属性;而对顶层母版页控件的访问却有多级Master属性,而Master属性的级数由嵌套的母版页层数所决定。例如,在上面的例子中,如果需要在内容页访问SiteOne.Master的txt_one控件,那么可以使用下面的语句进行访问:


Label one=

Master.Master.FindControl("txt_one")as Label;


之所以有两级Master属性,是因为它嵌套了两层母版页。

(2)对除顶级母版页以外的下一级母版页控件的访问

仍然以上面的例子为例,如果需要在内容页访问SiteTwo.Master的txt_two控件,则必须先从第二层得到第一层的ContentPlaceHolder,来访问其中的控件。如下面的代码所示:


ContentPlaceHolder twoMaster=

Master.Master.FindControl("One")as ContentPlaceHolder;

Label two=

twoMaster.FindControl("txt_two")as Label;


现在来看一个综合的例子,如下面的代码所示:


public partial class Test:System.Web.UI.Page

{

protected void Page_Load(object sender, EventArgs e)

{

//访问SiteOne.Master的txt_one控件

Label one=

Master.Master.FindControl("txt_one")as Label;

if(one!=null)

{

one.Text="修改第一个母版页里txt_one的值";

}

//访问SiteTwo.Master的txt_two控件

ContentPlaceHolder twoMaster=

Master.Master.FindControl("One")as ContentPlaceHolder;

Label two=

twoMaster.FindControl("txt_two")as Label;

if(two!=null)

{

two.Text="修改第二个母版页里txt_two的值";

}

}

}


在上面的代码中,分别访问并修改了SiteOne.Master文件的txt_one控件和SiteTwo.Master文件的txt_two控件的值。页面的结果如图14-12所示。

当然,除了上面这种方式外,还可以通过在母版页设置属性来间接访问该控件。

figure_0514_0399

图 14-12 嵌套母版页中的控件访问示例运行结果