屯昌旅游网

服务器控件开发 - 事件机制(3)

    在上一篇的基础上, 我们来看看如何为我们的服务器控件添加事件支持。 丰富的事件支持能让控件的使用者最大限度的参与控件的生命周期,最大限度得提高控件的重用性。
     每一个服务器控件都从Control基类继承了 OnInit, OnLoad, OnPreRender, and OnUnLoad 等 4 个事件. 在页面开发中, 开发人员可以通过2种方式来注册ASP.NET事件.
1. 通过声明的方式
     <asp:Button id="button1" OnClick="button1_Click" Text="Submit" runat="server" />
2. 通过编程的方式
     button1.Click += new EventHandler(this.button1_Click);
    另外一点需要注意的是, 在Asp.net 2.0 里面. 页面模型自动将Page_Init, Page_Load, Page_PreRender, and Page_Unload 4 个方法绑定到页面对应的事件.
而不需要显式的声明. 这个特性是通过在页面声明中加入 AutoEventWireup="true" 来实现的. 如果发现页面不触发Page_Load 事件. 一个可能的原因就是
AutoEventWireup 的值被设为 False.
    在C# 中 定义一个典型的事件代码如下:
Code
    然而, 在ASP.NET 中, 微软并没有采用这样一种方式来定义事件.而是基于Web 开发的特点进行优化, 采用了另外一种方式. 书中提到了2 点之所以不采用
    经典事件实现模式的原因:
    1.  不管事件是否被注册到具体的方法, 每当我们定义一个事件成员, 比如说    public event ClickEventHanlder OnClickEvent = null;  编译器都会为
        之生成一个私有的代理,比如: delegate void ClickEventHanlder(object sender, EventArgs e). 一但事件数目比较多, 将会浪费很多宝贵的内存空间
    2.  编译器会为经典事件模式生成一大堆的线程同步的代码. 这样不但降低了执行效率而且是毫无必要的, 因为页面开发者很少在单个页面使用多线程.
 
现在让我们来看一下针对于Asp.net 的优化的 基于System.ComponentModel.EventHandlerList 类的事件实现模式, 
首先来看看Control 中 OnInit 事件的实现.
 1. 声明一个 EventHandlerList  类型的事件索引,用来保存代理列表。
Code
 Control 基类为每一个事件定义了一个静态只读的键, 用来从EventHandlerList 中获取事件代理, 或者将事件代理添加到事件列表上.
Code
      注意这个键是静态共享的, 这意味着所有的控件的所有实例共享这个键.

 2. Control 基类使用一个事件属性来定义事件. 而不是使用事件成员.
Code

       当用户向事件列表添加一个事件代理, Events 类首先通过事件的键 判断 事件是否已经添加。 如果未添加, 则添加,如果键已经存在, 则将代理方法添加到键所对应的代理的代理列表上。
       当用户再事件列表移除一个事件代理, 过程刚好相反。

  3. 定义一个事件触发器, 通过一个hook, 调用代理方法。

Code


 最后  在页面的特定阶段触发事件, OnInit 事件的触发可以参考我第一篇当中的 InitRecursive方法

通过以上方式就可以任意的为我们的自定义控件添加事件。 而不需要去考虑任何的性能问题。

下一篇  : 服务器控件的 PostBack 机制。


posted on 2008-07-04 16:27  welkin  阅读(2102)  评论(9编辑  收藏  举报

导航

屯昌旅游网