2.3.1多层次的Master页面 虽然这种技术没有用于WroxUnited站点,但是页面可以继承多层次的Master页面。这个功能提供了一种显示多层次结构标准内容的方式。例如,一个名为Publication.aspx的Content页面可以指定它的Master页面为Research.master,而Research.master又指定它的Master页面为Corporate.master。最终显示的结果是,Publication.aspx包含在Research.master内,而Research.master页面又包含在Corporate.master内。这样做的一个问题是用于显示内容的空间将随着层次结构的增加而不断减少。VWD没有包含用于创建多层次Master的自动工具。事实上,如果包含了多个层次,那么只能在Source视图中打开页面。
要创建带有多层次Master的页面,必须在中间层页面中包含标记同时指明该页面的Master页面(上一个层)和内容占位符(为下一层页面提供)。回忆一下,在Master页面的第一行代码中必须包含<%@master… >,而在低一层的页面或者Content页面的第一行代码中必须包含<%@pagemasterPageFile=% >。如果是中间页面,它即是Content又是Master,那么第一行的标记必须以<%@master…开始,同时包含…masterPageFile=% >。
Master页面包含了一个<asp:ContentPlaceHolder >标记,而Content页面则包含了一个<asp:content >标记。如果是中间层页面,那么它必须包含一个<asp:content >标记,该标记与Master页面中的<asp:ContentPlaceHolder >标记相关联。然后在这个标记中有一个<asp:ContentPlaceHolder >标记,该标记用于包含下一层的页面。
下面的示例演示了一个CorporateMaster页面、一个ResearchdepartmentMaster页面和最终包含具体内容的Publication.aspx页面。下面的代码显示了Corporate页面。注意它的内容占位符是在阴影部分定义的:
<%@Master Language="VB"% >
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" >
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server" >
<title >CorporateMaster</title >
</head >
<body >
CorporationName
<form id="form1"runat="server" >
<div >
<asp:contentplaceholder id="ContentPlaceHolderCorporate" runat="server" >
</asp:contentplaceholder >
</div >
</form >
</body >
</html >
下面的代码演示了ResearchdepartmentMaster页面。这个页面最复杂,因为它既是Corporate页面的Content页面,同时也是Publication页面的Master页面。注意在第一行代码中,Master和MasterPageFile=将该页面设置为CorporateMaster页面的内容。然后可以注意到<asp:ContentPlaceHolder >将其他页面作为自己的内容(在这里是Publication页面)。内容占位符必须全部包含在<asp:content >标记之内:
<%@Master MasterPageFile="~/Corporate.master" Language="VB"% >
<asp:Contentrunat="server" ContentPlaceHolderID="ContentPlaceHolderCorporate" >
ResearchDepartment
<asp:contentplaceholder id="ContentPlaceHolderResearch" runat="server" >
</asp:contentplaceholder >
</asp:Content >
下面显示的是Publication.aspx页面的代码(其中只包含了网页的具体内容)。在此只需指定Master页面。这个页面不是Master页面,它位于最底层:
<%@Page Language="VB"MasterPageFile="~/Research.master"Title="UntitledPage"% >
<asp:ContentID="Content1" ContentPlaceHolderID="ContentPlaceHolderResearch" Runat="Server" >
Publicationtext
</asp:Content >
2.3.2Master页面支持多个内容占位符 到目前为止,本书的示例在Master页面中只使用了一个<asp:ContentPlaceHolder >,在Content页面中也只使用了一个<asp:content >标记。ASP.NET2.0支持多个内容占位符。但是,每个占位符都必须有自己的ID,如下例所示:
<%@Master Language="VB"% >
<html ><body >
<form id="form1" runat="server" >
<asp:contentplaceholder runat="server" id="TopContent"/ >
<asp:contentplaceholder runat="server" id="MiddleContent"/ >
<asp:contentplaceholder runat="server" id="BottomContent"/ >
</form >
</body ></html >
接下来就可以将内容包含在<asp:content >标记中,这些标记的ContentPlaceHolderID值与Master页面中的ID值相等:
<%@Page Language="VB" MasterPageFile="~/research.master" Title="UntitledPage"% >
<asp:ContentID="Content1" ContentPlaceHolderID="TopContent" Runat="Server" >
TexttogoinTopsection
</asp:Content >
<asp:ContentID="Content1" ContentPlaceHolderID="MiddleContent" Runat="Server" >
TexttogoinMiddlesection
</asp:Content >
<asp:ContentID="Content1" ContentPlaceHolderID="BottomContent" Runat="Server" >
TexttogoinBottomsection
</asp:Content >
将内容分别存放在不同的<asp:ContentPlaceHolder >标记中有助于设计和维护Master页面的布局。
为了使用ASP.NET2.0的导航功能,必须有一种标准的方法描述站点中的每个页面。这个标准不仅包含每个网页的名称,还应该能够表明它们的层次结构关系。例如,显示球员统计数据的页面应该是显示球员列表页面的子页面,而该页面又是主页的子页面:
Home
-Players
--Player
STATISTICS 定义这样的层次结构在站点设计中是一个很重要的部分,因为开发人员希望知道(在开始编写代码之前)需要开发什么页面、在不同的页面上应给用户提供哪些链接、以及用户在查看了一个特定的页面之后可能会浏览其他什么页面。画出站点的树型目录,就像上面的简单示例那样,这是必须采取的第一个步骤。然后可以进行下一个步骤,在代码中定义这个层次结构。
ASP.NET2.0在一个名为web.sitemap的XML文件中包含这些信息。可以将这个文件作为菜单和导航控件的数据来源,这一内容将在第3章讨论。
提示:
Microsoft在ASP.NET2.0中所提供的是一种在菜单和导航控件中使用站点数据的方式,前提是这些数据要遵守web.sitemap标准。VWD为web.sitemap文件提供了一个模板,该模板中包含了web.sitemap文件所需的标记。但在写作本书的时候,还没有工具可以扫描站点并生成存放在这些标记中的实际数据。第三方工具将填补这个空隙,但现在必须手动将这些信息输入到web.sitemap文件中。 站点地图必须是一个名为web.sitemap的XML文件,而且位于Web应用程序的根目录下。XML是一种保存数据的标准,有些类似于数据库,但以一种肉眼可以阅读的文本形式存放数据。每个数据项保存在一个节点中,其中节点表示站点的一个页面,包含页面的URL、标题和描述。XML文件以树型结构保存节点,因此ASP.NET2.0知道哪些页面应看作是某个父页面的子页面。例如,CorporateDepartments页面应该是显示Sales、Research和Accounting各部门详细信息页面的父页面。该文件中的第一个标记是标准的,用于让XML文件标识版本号和XMLNS,如下代码所示:
<?xmlversion="1.0"encoding="utf-8"? >
<site Mapxmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
这两行代码是由开发人员在VWD中使用站点地图模板添加该文件时由VWD自动输入的。节点的名称很简单:<siteMap >,该标记包含了多个<siteMapNode >标记。每个标记代表一个网页,而且可以包含以下属性(<siteMapNode >标记的所有属性都是字符串):
●Title:描述页面(这与页面头部的<Title >标记没有任何联系,虽然它们的值可以相同)。
●URL:节点中描述的页面位置。
●Description:该页面的描述。
注意在一个URL中可以包含querystring数据,这是定义在页面URL之后的附加信息,作为页面请求的一部分发送给服务器。例如,通常引用一个页面的方式应该类似下面的第一行代码,而附带数据引用一个页面(例如,在日历中显示的月份)的方式将类似于下面的第三行代码:
url="Calendar.aspx"
url="Calendar.aspx?Month=May"
站点地图中页面之间的层次结构关系(父/子关系)是通过将子节点包含在父节点的开标记和闭标记之间建立起来的。注意在下面的代码中两个子页面(Members和Calendar)是如何包含在Home页面的开和闭标记(灰色背景显示)内的。缩进只是为了便于阅读;并不会影响实际的层次结构关系。注意表示子页面(Members和Calendar)的标记可以使用单标记形式<Tag…/ >。但是由于父页面(Home)拥有子页面(它包含其他节点),因此它必须使用双标记形式<Tag >…</Tag >:
<siteMap >
<siteMap Nodetitle="Home" url="Default.aspx" description="HomepageforMySite" >
<siteMap Nodetitle="Members" url="Members.aspx" description="AllMembers"/ >
<siteMap Nodetitle="Calendar" url="Calendar.aspx" description="ClubEvents"/ >
</siteMapNode >
</siteMap >
为了在Calendar节点内创建两个子页面(Home页面的子页面),需要采取两个步骤。首先,将表示Calendar的<siteMapNode >转换成双标记形式,然后在这个标记的内部添加两个子标记,如下面代码的灰色部分所示。记住,如前所述,必须在web.sitemap文件的Source视图中手动完成输入。VWD既没有提供可以执行自动扫描和生成数据的工具,也没有提供从SolutionExplorer到web.sitemap文件的拖放功能。
<siteMap >
<siteMap Nodetitle="Home" url="Default.aspx" description="HomepageforMySite" >
<siteMap Nodetitle="Members" url="Members.aspx" description="AllMembers"/ >
<siteMap Nodetitle="Calendar" url="Calendar.aspx" description="ClubEvents" >
<siteMap Nodetitle="CalendarofRacingEvents" url="Calendar\Racing.aspx"description="RacingEvents"/ >
<siteMapNodetitle="CalendarofSocialEvents" url="Calendar\Social.aspx"description="SocialEvents"/ >
</siteMapNode >
</siteMapNode >
</siteMap >
注意在<SiteMapNode >节点中可以指定另一个属性:roles。在第11章将看到,在WroxUnited示例的站点地图文件中用到了这个属性。在有些情况下,开发人员可能希望让用户知道某个页面的存在,即使该用户没有访问这个页面的权限。以这种方式,可以向用户提供一个链接,但当用户单击这个链接的时候,站点将提示他先以拥有足够权限的用户身份进行登录,然后才能查看这个页面。
在下一个“试一试”部分,将为WroxUnited创建web.sitemap。在下一章中才能看到这个练习的结果,在那里将学习导航控件的概念。但这个步骤是将站点结构的纸上设计转入到代码的一种方式,所以正确地完成它是很重要的。
(1)在SolutionExplorer中右击根目录并选择AddNewItem。选择名为SiteMap的模板并将该文件命名为web.sitemap。注意VWD自动添加了前两个标记并给出了3个节点的架构。第一个是最高层次(Home),其他两个是子层次。
(2)用下面的代码修改第一个<siteMapNode >,使其表示Home页面:
<siteMapNodetitle="Home"url="Default.aspx"description="WroxUnitedHomePage" >
(3)修改下一个<siteMapNode >(第一个子节点):
<siteMapNodetitle="Fixtures"url="Fixtures.aspx"description="MatchFixtures" >
(4)将整个空白<siteMapNode >复制到剪切板以便粘贴它,而不必重复输入该标记。
(5)为Fixtures节点创建两个子节点,如下面的灰色代码所示:
<
siteMap Nodetitle="Fixtures" url="Fixtures.aspx" description="MatchFixtures" >
<siteMap Nodetitle="FutureFixtures" url="Fixtures.aspx?type=future" description="Whowe'regoingtobeplaying"/ >
<siteMapNodetitle="PastFixtures"
url="Fixtures.aspx?type=past"
description="Whowe'vealreadyplayed"/ >
</siteMapNode >
(6)要完成这个示例,还需添加一定数量的节点,所以为了节约时间,我们将其他节点包含在本章目录(C:\BegASPNET2\Chapters\begin\Chapter02)下一个名为web.sitemap.remainder的文件中。您所需做的就是在Notepad中打开这个文件,复制该文件的所有内容,并将其粘贴到您所创建的文件的底部。另一种选择是,导入作者创建的web.sitemap文件。
(7)暂时无法测试web.sitemap文件,因为显示这些数据的控件要在第3章中才讨论,但理解这个基础是很重要的,因为可以使用它为站点添加导航功能。
操作回顾 在这个练习中创建一个站点地图文件。VWD没有包含可以自动创建该文件的工具,但包含了一个简单的模板,该模板提供一些标记作为工作的起点。该文件只有命名为web.sitemap才能为ASP.NET2.0使用,所以不要试图改变该文件的名称。
添加一个新的站点地图模板并切换到Source视图。VWD添加了起始标记和第一个节点的标记。但接下来必须手动输入所有数据,并开始为其他页面及其数据复制和粘贴标记。显然,编写程序自动实现这个任务的第三方软件将会很畅销!
在开始设计任何Web站点之前,回顾一下优秀站点设计的原则是很有益的。在本书中,应该记住三个基本概念:
●尽量将信息与其表示分隔开。例如,开发人员将设计页面的标题、布局和格式(表示)。在页面上,开发人员将放置配置好的控件以获取和显示信息(例如球队的球员列表)。通过将这些目标分隔开,开发人员可以分别对每个部分进行更新而不会影响到其他部分。例如,当球队增加了一名新球员时,关于该球员的信息将保存在数据库中,页面将自动显示新的球员列表而无需修改表示层。
●尽量保证站点具有一致的外观。通过使用相同的色彩、图标和屏幕布局,可以为用户创建一种临场感(senseofpresence)。忠实的球迷一看到这种色彩就感觉像到了家一样。回访用户可以利用已经掌握的经验使用该站点。
●尽量简化站点导航。首先,所有页面上的菜单条将简化从站点的一个部分跳转到另一个部分的导航。用户还将使用ASP.NET2.0工具显示当前正在查看的页面位于站点中的什么位置。
ASP.NET2.0使用两个文件保存用于整个站点的配置信息和代码,这一点所有ASP.NET站点都是一样的。这两个文件分别是Web.config和Global.asax。
●Web.config包含站点的配置信息;例如,指定一个定制的标准错误页面,当站点内发生错误时,向终端用户显示这个页面。
●Global.asax包含处理事件的代码,这些事件由站点的任意页面产生;例如,当用户第一次访问站点时运行的代码(会话初始化)。