我们一直在服务器端的代码中使用各种事件,而这些事件大多是专用于特定的服务器控件的。我们可以在这些事件中定义我们所需要的操作,如Button的Click事件。但是我们还希望在创建的删除页面时执行某些操作,幸运的是,ASP.NET页面在页面的生命周期内给我们定义了许多事件来完成这些操作。而这也为我们PageBase类的编写提供了条件。在这篇文章中,通过对页面事件的分析,完成了PageBase类的编写。
我们一直在服务器端的代码中使用各种事件,而这些事件大多是专用于特定的服务器控件的。我们可以在这些事件中定义我们所需要的操作,如Button的Click事件。但是我们还希望在创建的删除页面时执行某些操作,幸运的是,ASP.NET页面在页面的生命周期内给我们定义了许多事件来完成这些操作。而这也为我们PageBase类的编写提供了条件。
一、页面生命周期的事件
在页面的生命周期内,定义了如下事件:
PreInit,Init,InitComplete,PreLoad,Load,LoadComplete,PreRender,PreRenderComplete和UnLoad事件,在每一个事件中,我们都可以根据需要来定义我们自己的操作。现把几个比较常用和重要的页面事件所完成的操作归结如下:
- Page_Init:出现此事件期间,您可以初始化值或连接可能具有的任何事件处理程序。
- Page_Load:出现此事件期间,您可以执行一系列的操作来首次创建 ASP.NET 页面或响应由投递引起的客户端事件。在此事件之前,已还原页面和控件视图状态。使用 IsPostBack 页面属性检查是否为首次处理该页面。如果是首次处理,请执行数据绑定。此外,请读取并更新控件属性。
- Page_DataBind:在页面级别调用 DataBind 方法时,将引发 DataBind 事件。如果在单个控件上调用 DataBind,则它只激发它下面控件的 DataBind 事件。
- Page_Unload:完成页面呈现之后,将激发 Page_Unload 事件。此事件是执行最终清理工作的合适位置。这包括清理打开的数据库连接、丢弃对象或关闭打开的文件等操作。
有了这些事件和在事件内需要定义的操作后,我们就可以编写我们的PageBase类了。
二、PageBase类的编写
在编写PageBase类之前,要清楚所有页面的公共行为和属性。以一般的信息管理系统为例,页面的公共行为和属性一般如下:
- 取得数据库
- 判断用户是否登陆
- 取得当前用户,并判断用户的权限。
- 初始化页面的查询条件
- 加载页面的样式表(如果页面需要动态加载样式表)
有了这些,我们开始编写我们的PageBase类,当然,这个类必须继承于System.UI.Web.Page类。
1>定义页面的属性,我们将数据库和当前用户定义为页面的属性,我们还可以取得页面的HTTP响应和判断页面在执行过程中是由使用了事务(可重写)。代码如下:
Code
/// <summary>
/// 用于保存登陆用户ID的Session的名称
/// </summary>
public const string SESSION_USER_ID = "UserID";
private Database _Database = DatabaseGateWay.GetNewDatabase();
private User _User;
/// <summary>
/// 取得数据库访问
/// </summary>
public Database Database
{
get { return _Database; }
}
/// <summary>
/// http响应
/// </summary>
public new HttpResponse Response
{
get { return base.Response; }
}
/// <summary>
/// 当前用户
/// </summary>
public new User User
{
get { return _User; }
}
/// <summary>
/// 页面的执行过程是否使用事务
/// </summary>
protected virtual bool UseTransaction
{
get { return false; }
}
2>重写页面的事件,并在这些事件中定义我们的操作。,在这个PageBase类中,重写了InitComplete,Load,UnLoad和Dispose事件。
在InitComplete事件中,取得了当前用户,判断用户是否登陆和初始化查询条件(可重写),代码如下:
Code
/// <summary>
/// 重载的初始化完成,构造查询条件
/// </summary>
/// <param name="e"></param>
protected override void OnInitComplete(EventArgs e)
{
if (UseTransaction)
{
Database.Connection.Open();
Database.Transaction = Database.Connection.BeginTransaction();
}
if (Session[SESSION_USER_ID] != null)
_User = _Database.Users.GetByID(Convert.ToInt32(Session[SESSION_USER_ID]));
if (_User == null)
this.Js_TopRedirect("Login.aspx", "你尚未登录或登陆已过期!");
base.OnInitComplete(e);
InitialQueryCondition();
}
/// <summary>
/// 初始化查询条件
/// </summary>
protected virtual void InitialQueryCondition()
{ }
在这个事件中,我们定义了一个虚方法InitialQueryCondition(),可以根据需要在页面中重写这个方法。
在Load事件中,我们判断了用户的权限,加载了页面的样式表,完成了页面数据绑定和定义了当页面第一次加载时的方法(可重写),代码如下:
Code
/// <summary>
/// 重载的加载函数,添加了初始化用户、判断用户登陆、判断用户权限和加载对应Css的功能。
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
if (!CheckPower())
{
this.Js_ShowMessage("对不起,您没有该操作的权限。");
Response.End();
}
addStyleSheetLink(User.UserRole.Type.ToString());
if (!IsPostBack)
{
Display();
DataBind();
}
base.OnLoad(e);
}
private void addStyleSheetLink(string styleSheetName)
{
Literal link = new Literal
{
Text = string.Format("<link href=\"Stylesheet/{0}.css\" rel=\"stylesheet\" type=\"text/css\" />", styleSheetName)
};
base.Page.Header.Controls.Add(link);
}
/// <summary>
/// 用于判断用户是否具有当前操作的权限。
/// </summary>
/// <returns>用户是否具有当前操作的权限</returns>
protected virtual bool CheckPower()
{
return true;
}
/// <summary>
/// 显示
/// </summary>
protected virtual void Display()
{
}
在Unload和Dispose事件中,定义了提交事务和断开数据库连接操作,代码如下:
Code
/// <summary>
/// 页面卸载时,提交事务
/// </summary>
/// <param name="e"></param>
protected override void OnUnload(EventArgs e)
{
if (UseTransaction)
{
Database.Transaction.Commit();
Database.Connection.Close();
}
}
/// <summary>
/// 页面销毁时,关闭未关闭的连接
/// </summary>
public override void Dispose()
{
if (UseTransaction)
{
if (Database.Connection.State != System.Data.ConnectionState.Closed)
Database.Connection.Close();
}
}
到目前为止,我们根据我们自己的需要完成了页面的基类,当然,这个基类不是固定的,根据不同的需要可以在不同的事件中定义不同的操作。