.net组件开发系列之武术系列 武术招数 控件生命周期与控件事件机制

 .net组件开发系列之武术系列   武术招数  控件生命周期与控件事件机制
一。控件生命周期

    先回述上篇,可能表述没有不清晰,也可能跨度大了点,好的,我们来一个循序渐进过程,大家都知道,武术都有招术的,先出什么,再出什么,什么时候打完收工,都是有顺序的,而我们的控件也正如此,它也有一个顺序。那我们的这个顺序(控件的生命周期)是怎么的.在web这个无状态http协议的通信中,如何实现了,如何创建一个象webform程序那样呢。使页面提供一个连续执行的。答案是。在处理完一个请求之后保存其状态,在回传时,在新的请求之前恢复已保存的状态。
  页面(其实也是一个控件,继承webcontrol)把请求分成几个阶段,能够用于重新创建和保存页面及控件树。那好,我们来看看控件生命期图:

 (ps:画得不乍的)

 关于控件生命周期各个阶段所发生的事,网上很多很多,详见:
http://blog.csdn.net/SysBug/archive/2007/06/04/1638013.aspx(
很详细的)

我们的主要在于分析执行机制,分了说明其执行顺序,我们举个例先:
 
我们在这样做的。就是重写控件生命周期的每个阶段,并且写入一些简单消息,然后,我们分三种。我们先将控件直接注册到页面上,一种是动态注册控件,一种是实例化控件,但不加到控件树上。然后通过启用trace="true"去页面追踪.
先了一个控件,代码如下:

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

/**//// <summary>
/// ConDemo 
的摘要说明
/// </summary>
/// 
namespace cnblogs
{
    
public class ConDemo : Control
    {
        
protected override void OnInit(EventArgs e)
        {
            
base.OnInit(e);
            Page.Trace.Warn(
this.UniqueID, "
在初始化阶段");
        }
        
protected override void TrackViewState()
        {
            
base.TrackViewState();
            Page.Trace.Write(
this.UniqueID, "在加载视图。。。");
        }
        
protected override void LoadViewState(object savedState)
        {
            
base.LoadViewState(savedState);
            Page.Trace.Write(
this.ID, "在保存视图阶段");
        }
        
protected override void OnLoad(EventArgs e)
        {
            
base.OnLoad(e);
            Page.Trace.Write(
this.UniqueID, " 在加载中。。。");
        }
        
protected override object SaveViewState()
        {
            Page.Trace.Write(
this.UniqueID, " 在保存视图状态..");
            
return base.SaveViewState();
            
        }
        
protected override void OnPreRender(EventArgs e)
        {
            
base.OnPreRender(e);
            Page.Trace.Write(
this.UniqueID, "在预呈现");
        }
        
protected override void Render(HtmlTextWriter writer)
        {
            Page.Trace.Write(
this.UniqueID, "在呈现..");
            
base.Render(writer);
        }
        
public override void Dispose()
        {
           
            
base.Dispose();
        }
        
public ConDemo()
        {
            
//
            // TODO: 
在此处添加构造函数逻辑
            //
        }
    }
}

 

然后在aspx 写上如下代码

注意:记得启动 Trace="true"

<%@ Page Language="C#"  Trace="true" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Namespace="cnblogs" TagPrefix="tt" %>
<!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>
    
<tt:ConDemo runat=server ID="Condemo1"></tt:ConDemo>
          <%--
控件添加 --%>
        
<asp:Button ID="Button1" runat="server" Text="加载控件" OnClick="Button1_Click" />
        
      <%--
产生回传 --%>
        
<asp:Button ID="Button2" runat="server" Text="postback" /></div>
    
</form>
    
</body>
</html>

cs页面

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class _Default : System.Web.UI.Page 
{
    
protected void Page_Load(object sender, EventArgs e)
    {

    }
    
protected void Button1_Click(object sender, EventArgs e)
    {
        cnblogs.ConDemo dy = 
new cnblogs.ConDemo();
        dy.ID="dynamic1";
        
this.Controls.Add(dy);
        cnblogs.ConDemo dy2=
new cnblogs.ConDemo();
        dy2.ID="dynamic2";
    }
}

 这些工作做完后,我们来分析分析现象。当我在第一次在浏览器浏览时:我们发现,子控件会在在预览的时候,可以发现阶段Condemo1(自定义控件)的执行顺序,当它被加到父控件的Controls里时,父控件会根据其当前的control阶段来调用该子控件的一些方法,让子控件赶上父控件的control阶段,

 

   

 
    (
1

 
每一个控件内部都保存着它当前的加载进度,也就是它到达了上述的哪一个阶段,当我们执行Control.Controls.Add方法来将一个控件添加到另一个控件中时,父控件就会检查子控件的加载进度,如果子控件的加载进度比自己的慢了,就会要求子控件追赶上来,

当我们点击"加载控件"按钮时,发现:
 

 (
两张图是一起的,截图的时候的不好截)
     
(图2
蓝色代表,是动态添加的,红色是我们在页面上直接注册的。
但我们在button 事件还创建了一个自定义控件(dynamic2)实例,可我们没有把它添加到控件树上,所以说,除非控件添加到控件树上,否则它不将参于请求处理,当在页面上注册控件时,页面的解析器会把它加到控件树上,动态创建的控件,则要自已将控件添加到控件树上。
从上面图中,我们还可以看到,另一个信息,就是我们为什么动态添加的控件在回传后会消失,从图中,一眼就看出来了,按图2来说吧,因为当dynamic1动态加载到控件树上时,可这个控件树(这里指的是Page页面)已经完成了加载视图状态,从而在后来的恢复视图中找不到了dynamic1中的视图了。这样就解析了动态控件回传后为什么会消失的问题,经过分析,你可能已经知道了,我们点了"postback"按扭后,控件树,变成什么样了吧。
 
现在问题出现了,该如何解决呢?
介绍两种方法吧:
第一种,就是在OnInit事件中动态加载进去,
示例:
 

 protected override void OnInit(EventArgs e)
    {  cnblogs.ConDemo dy= 
new cnblogs.ConDemo();
        dy.ID="dynamic1";
        
this.Controls.Add(dy);
        dy.Visible = 
false;
        
base.OnInit(e);
    }

然后在按扭事件中。查找dynamic1控件,将其Visibletrue
第二种,见我的(动态添加控件终极解决方案)

地址:http://www.cnblogs.com/suiqirui19872005/archive/2007/10/11/920845.html


二:下一讲事件机制,
原本想今天写事件机制一并写掉,可我没有准备好示例,所以,等下一讲讲吧。
先透露一下,大家都常用IPostBackDataHandler,IPostBackEventHandler了吧,
下一讲还有两个事件注册。GetPostBackClientHyperlink,GetPostBackEventReference

我们都用过LinkButton吧,我们发现其生成html后,成了
javascript:__doPostBack('LinkButton1',''),
其中就用了GetPostBackClientHyperlink,下一节中,将讲到。

 

 


PS
自已的表达能力差了点,望大家海含,我在更正当中。

posted @ 2007-10-15 14:03  过河卒A  阅读(3155)  评论(7编辑  收藏  举报