如有不明白的地方欢迎加QQ群14670545 探讨
主要经理11个过程:
新建类库CustomerWebControls,添加类ControlLifeCycle.cs,写入代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Specialized;
#region //服务器控件生命周期所要经历的11个阶段
/*
* (1)初始化-- --在此阶段中,主要完成两项工作:一、初始化在传入Web请求生命周期内所需的设置;二、跟踪视图状态。首先,页面框架通过默认方式引发Init事件,
* 并调用OnInit()方法,控件开发人员可以重写该方法为控件提供初始化逻辑。此后,页面框架将调用TrackViewState方法来跟踪视图状态。
* 需要注意的是:多数情况下,Control基类提供的TrackViewState方法实现已经足够了。只有在控件定义了复杂属性时,开发人员才可能需要重写TrackViewState方法。
* (2)加载视图状态----此阶段的主要任务是检查服务器控件是否存在以及是否需要将其状态恢复到它在处理之前的请求结束的状态。因此该过程发生在页面回传过程中,
* 而不是初始化请求过程。在此阶段,页面框架将自动恢复ViewState字典。如果服务器控件不维持其状态,或者它有能力通过默认方式保存其所有状态而使用ViewState字典,
* 那么开发人员则不必实现任何逻辑。针对那些无法在 ViewState字典中存储的数据类型或者需要自定义状态管理的情况,开发人员可以通过重写LoadViewState方法来自定义状态的恢复和管理。
* (3)处理回发数据----若要使控件能够检查客户端发回的窗体数据,那么必须实现System.Web.UI.IPostBackDataHandler接口的 LoadPostData()方法。因此只有处理回发数
* 据的控件参与此阶段。
* (4)加载----至此阶段开始,控件树中的服务器控件已创建并初始化、状态已还原并且窗体控件反映了客户端的数据。此时,开发人员可以通过重写OnLoad()方法来实现每个请求共同的逻辑。
* (5)发送回发更改通知----在此阶段,服务器控件通过引发事件作为一种信号,表明由于回发而发生的控件状态变化(因此该阶段仅用于回发过程)。为了建立这种信号,
* 开发人员必须再次使用System.Web.UI.IPostBackDataHandler接口,并实现另一方法- RaisePostBackChangedEvent()。其判断过程为:如果控件状态因回发而更改,
* 则LoadPostData()返回true;否则返回false。页面框架跟踪所有返回true的控件并在这些控件上调用RaisePostDataChangedEvent()。
* (6)处理回发事件----该阶段处理引起回发的客户端事件。为了便于将客户端事件映射到服务器端事件上进行处理,开发人员在此阶段可以通过
* 实现 System.Web.UI.IPostBackEventHandler接口的RaisePostBackEvent()方法来实现该逻辑。由此途径,服务器控件将成功捕获回发的客户端事件进行服务器端的相应处理。
* (7)预呈现----该阶段完成在生成控件之前所需要的任何工作。通常情况下是通过重写OnPreRender()方法完成该工作。需要注意的是:在该阶段,可以保存在预呈现阶段对控件状态所做的更改,而在呈现阶段进行的更改则会丢失。
* (8)保存状态----如果服务器控件不维持状态,或者它有能力通过默认方式保存其所有状态而使用ViewState字典,那么开发人员不必在该阶段实现任何逻辑。因为这个保存状态的过程是自动的。
* 如果服务器控件需要自定义状态保存,或者控件无法在ViewState字典中存储特殊的数据类型,则需要通过重写SaveViewState()方法来实现状态保存。
* (9)呈现----表示向HTTP输出流中写入标记文本的过程。开发人员通过重写Render()方法使其在输出流上自定义标记文本。
* (10)处置----在此阶段中,通过重写Dispose ()方法完成释放对昂贵资源的引用,如数据库链接等。
* (11)卸载----完成的工作与"处置"阶段相同,但是,开发人员通常在Dispose()方法中执行清除,而不处理Unload事件。
*
* 小结:服务器控件在ASP.NET框架中起着举足轻重的作用,是构建Web应用程序最关键、最重要的组成元素。对于一个优秀的开发人员,
* 掌握服务器控件的基础知识是非常重要的。本文就服务器控件的概念、类型、生命周期等关键内容进行了介绍。希望读者能够将这些内容牢固掌握,
* 为写出精彩的服务器控件打下良好的基础。
*/
#endregion
namespace CustomerWebControls
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:ControlLifeCycle runat=server></{0}:ControlLifeCycle>")]
public class ControlLifeCycle : WebControl, IPostBackDataHandler, IPostBackEventHandler
{
/// <summary>
/// 输出
/// </summary>
/// <param name="content"></param>
private void Output(string content)
{
if (!this.DesignMode)
{
HttpContext.Current.Response.Write(content + "<br/>");
}
}
/// <summary>
/// 1.控件的初始化
/// </summary>
/// <param name="e"></param>
protected override void OnInit(EventArgs e)
{
Output("1. OnInit");
base.OnInit(e);
this.Page.RegisterRequiresPostBack(this);
}
/// <summary>
/// 2.装载视图
/// <remarks>此阶段的主要任务是检查服务器控件是否存在以及是否需要将其状态恢复到它在处理之前的请求结束的状态</remarks>
/// </summary>
/// <param name="savedState"></param>
protected override void LoadControlState(object savedState)
{
Output("2. LoadControlState");
base.LoadControlState(savedState);
}
/// <summary>
/// 3.回传数据处理
/// <remarks>实现IPostBackDataHandler接口的LoadPostData方法,因此只有处理回发数据的控件参与此阶段。</remarks>
/// </summary>
/// <param name="postDataKey"></param>
/// <param name="postCollection"></param>
/// <returns></returns>
public virtual bool LoadPostData(string postDataKey, NameValueCollection postCollection)
{
Output("3. LoadPostData");
return true;
}
/// <summary>
/// 4.加载事件
/// <remarks>至此阶段开始,控件树中的服务器控件已创建并初始化、状态已还原并且窗体控件反映了客户端的数据</remarks>
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
Output("4. OnLoad");
base.OnLoad(e);
}
/// <summary>
/// 5. 回传事件通知
/// <remarks>实现IPostBackDataHandler接口的RaisePostDataChangedEvent方法</remarks>
/// </summary>
public virtual void RaisePostDataChangedEvent()
{
Output("5. RaisePostDataChangedEvent");
}
/// <summary>
/// 6. 处理回传事件
/// <remarks>实现IPostBackEventHandler接口的RaisePostBackEvent方法</remarks>
/// </summary>
/// <param name="eventArgument"></param>
public virtual void RaisePostBackEvent(string eventArgument)
{
Output("6. RaisePostBackEvent");
}
/// <summary>
/// 7. 预呈现
/// </summary>
/// <param name="e"></param>
protected override void OnPreRender(EventArgs e)
{
Output("7. OnPreRender");
base.OnPreRender(e);
}
/// <summary>
/// 8. 保存视图状态
/// </summary>
/// <returns></returns>
protected override object SaveViewState()
{
Output("8. SaveViewState");
base.SaveViewState();
return new Pair();
}
/// <summary>
/// 9. 呈现
/// </summary>
/// <param name="writer"></param>
protected override void Render(HtmlTextWriter writer)
{
/*
* Page.ClientScript.GetPostBackEventReference方法:
* 返回一个可以在客户端事件中使用的字符串,以便回发到服务器。
* 该引用字符串由处理回发的指定控件和一个附加事件信息的字符串参数定义。
*/
writer.Write("<input type='button' name='{0}' value='Click Me(Render时呈现)' style='position:absolute;left:20px;top:280px' οnclick=\"{1}\"/>",
"[控件生命周期]", Page.ClientScript.GetPostBackEventReference(this, ""));
Output("9. Render");
base.Render(writer);
}
/// <summary>
/// 10. 卸载
/// <remarks>当服务器控件从内存中卸载时发生。释放对昂贵资源的引用,如数据库链接等。</remarks>
/// </summary>
/// <param name="e"></param>
protected override void OnUnload(EventArgs e)
{
Output("10. OnUnload");
base.OnUnload(e);
}
/// <summary>
/// 11. 释放资源
/// </summary>
public override void Dispose()
{
Output("11. Dispose");
base.Dispose();
}
}
}
将CustomerWebControls编译生成以下,web层引用此层。
web层新建页面controlcycle.aspx,头部注册下自定义的控件
<%@ Register Assembly="CustomerWebControls" Namespace="CustomerWebControls" TagPrefix="cc1" %>
全部代码如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="controlcycle.aspx.cs" Inherits="MyWebSiteTest.controlcycle" %>
<%@ Register Assembly="CustomerWebControls" Namespace="CustomerWebControls" TagPrefix="cc1" %>
<!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>
<cc1:ControlLifeCycle runat="server" />
</div>
</form>
</body>
</html>
预览以下看到首先看到如下效果
有几个事件没有出来,为什么呢,因为事件2,、3、5、6是发生在回发之后的,单击button按钮,再看效果
事件2还是没有出来,因为视图状态无需处理