实现这个例子的模板代码如下:
<% @ Register TagName = " AwardHeader " TagPrefix = " CC " Src = " AwardHeader.ascx " %>
<% @ Register TagName = " AwardNav " TagPrefix = " CC " Src = " AwardNav.ascx " %>
< HTML >< HEAD >
< LINK href = " ../default.css " type = " text/css " rel = " stylesheet " >
</ HEAD >
< body onload = " javascript:onload(); " >
< form id = " Form1 " method = " post " runat = " server " >
< div >< CC:AwardHeader runat = " server " ID = " Header1 " /></ div >
< div style = " WIDTH:100% " >
< table width = " 100% " border = " 0 " cellpadding = " 0 " cellspacing = " 0 " id = " TableTemplate " >
< tr >
< td style = " width:150px " >
< CC:AwardNav runat = " server " ID = " Awardnav1 " />
</ td >
< td valign = " top " align = left >
< asp:PlaceHolder id = " _placeHolder " runat = " server "
EnableViewState = " False " />
</ td >
</ tr >
</ table >
</ div >
</ form >
</ body >
</ HTML >
在这部分代码中,是将页面公共部分做成了控件,然后在模板中注册。尽管在每一个页面中注册一遍控件所需代码也不是很多,但通过模板维护公共部分有一个好处:可以更快速地改变整个应用程序的外观、布局、颜色等,也可以准备多个不同的模板,并为不同的页面选择其合适的模板。
Page基类
要采用模板来实现页面,除了要将模板的内容包含起来,往往还要在页面中替换或者填充模板中的一些内容。这些装载、转换工作既然也是每一个页面都要做的事情,当然也可以将它们放到一个单独的类中实现,这就是Page基类。
Page基类在ASP.NET中的角色是公共的控制器。我们可以将每一个页面都要实现的控制逻辑放到此处。
下面的代码文件是实现图2的Page基类。
using System;
using System.Collections;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace MyNameSpace
{
/** <summary>
///系统各页面的BasePage
/// 作用:通过装载模板为各个页面加载公共布局,包括Header、导航条、页脚
/// </summary>
public class MyBasePage:Page
{
PlaceHolder _container;
string _templatePath = "Template1.ascx";
public MyBasePage()
{
_container = new PlaceHolder();
_container.ID = "_container";
}
protected string TemplatePath
{ //允许指定不同的模板文件
get { return _templatePath; }
set { _templatePath = value; }
}
protected override void OnInit(EventArgs e)
{
//装载模板文件
Control template = LoadControl(_templatePath);
if (template == null)
throw new Exception("装载模板文件错误!");
Control placeHolder =
template.FindControl("_placeHolder");
if (placeHolder == null)
throw new Exception("模板文件格式错误");
placeHolder.Controls.Add(_container);
for (int i=0; i<template.Controls.Count; i++)
{
Control c = template.Controls[0];
template.Controls.Remove(c);
Controls.Add(c);
}
base.OnInit(e);
}
}
}
其它页面继承Page基类,而不是继承默认的System.Web.UI.Page类。
//page1.aspx.cs
public class page1 : MyBasePage
{
//
}
<!—page1.aspx
<%@ Page Inherits="page1" CodeBehind="page1.aspx.cs" Language="c#" AutoEventWireup="false" %>
<h5>This is page1</h5>
公共的Page基类可以做很多事情,常见的如对错误(Exception)的处理、接收页面传递的字段、URL与字符集转换、增加客户端脚本等。
在性能方面,使用ACT测试的结果表明,使用Page基类和模板技术带来的性能损失非常有限。
最后,顺便提到一下笔者认为非常有意思的一点:在ASP.NET中,无论是模板、Page基类、还是独立的页面,都可以同时具有视图文件(.aspx文件)和代码文件(.cs文件)其中之一或者全部。例如,在微软资助出版的ESP(即.NET企业解决方案模式)书籍中,就提供了另外一种Page基类,该page基类的视图文件就是各个页面的公共视图,也相当于我们这里的模板文件。ASP.NET中这种灵活的机制既为大多数开发人员提供了方便,也同时增加了犯错的可能---尽管你可以用多种方式实现同样的功能,但最佳的方式是什么呢?正如我们已经找到了复用MVC三者中任何一种的方式,但对于MVC究竟是分离还是合并到一起,仍然需要根据应用程序的复杂程度等实际情况做出选择。