第一章 .Net 控件开发(WebForm) 开发简单自定义控件(7) 控件事件的引发以及优化

 1、到了上章,我们基本上把有关界面样式的东西都做好了,按照常理来说我现在就差个点击按钮弹出个对话框,就是我们第一章的初始的那个图片,我们要实现这个事件要执行以下三个步骤:(1)实现或者选择合适的事件数据类(2)生命或者选择何时的事件委托类(3)使用自定义控件引发事件。

2、 先实现事件数据和事件委托类,定义一个继承EventArgs类叫TestEventArgs3,并申明个属性,构造函数里面实例化,凡是自定义数据的要么直接引用系统已经写好的,要么自定义继承EventArgs类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebFormControl
{
    public class TestEventArgs3:EventArgs
    {
        private string textname;
        public string TextName
        {
            get { return textname; }
            set { textname = value; }
        }

        public TestEventArgs3(string textname)
        {
            this.textname = textname;
        }
    }
}

3、 自定义了事件数据类,所以还必须申明一个委托,默认的规则是,该委托包含两个参数,第一个是System.Object类型,并且应该是引发事件的自定义控件的实例,第二个参数应该是自定义事件数据类的实例。不了解委托的朋友要了解下委托,否则很难明白到底是怎么回事。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebFormControl
{
    public delegate void TestEventHandler3(object sender,TestEventArgs3 e);
}

4、 定义个控件类继承TestControl2叫TestControl3,首先自定义控件必须使用委托实例和关键字event来定义事件,还要实现一个受保护的虚方法,该方法调用事件委托以便将通知发送给客户端。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebFormControl
{
    public class TestControl3:TestControl2
    {
        public event TestEventHandler3 Test;
        protected virtual void OnTest(TestEventArgs3 e)
        {
            if (Test != null)
            {
                Test(this, e);
            }
        }
    }
}

5、我们把TestControl3拖到界面上,可以看到事件里有个Test事件了,我们先在里面写事件,我们现在只管能不能写就好,先不管能不能弹出个窗

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<%@ Register Assembly="WebFormControl" Namespace="WebFormControl" 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>
    <style type="text/css">
        #TestControl31 tr td
        {
            border-color: Black;
            border-style: solid;
            border-width: 1px;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <cc1:TestControl3 ID="TestControl31" runat="server" BorderCollapse="Collapse" 
            ontest="TestControl31_Test" />
    </div>
    </form>
</body>
</html>

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            
        }
    }
    protected void TestControl31_Test(object sender, WebFormControl.TestEventArgs3 e)
    {
        Response.Write("<script>alert(" + e.TextName + ")</script>");
    }
}

 6、 事件基本上可以实现了,我把Test事件定义为一个公共字段,将自定义控件的事件委托定义为字段会引发以下两个问题:(1)无论客户端是否已经将委托添加到事件委托的调用列表中,编译器都会为自定义控件的每个事件委托字段生成一个私有委托字段。这浪费了很多服务器内存,尤其是当自定义控件公开了多个事件的时候;(2)编译器为自定义控件的每个事件委托字段都生成一个Add和一个Remove方法。当客户端使用+=和-=符号添加和移除自定义控件事件委托的调用列表中的委托时,将调用这两种方法。这些编译器生成的方法是线程安全的,也就是说,它们保罗了额外的代码来同步访问这些方法的线程。这意味着客户端每次从自定义控件的事件委托中添加或者移除委托时,它们必须首先进行锁定,这样导致了一个不必要的开销,因为多数页面开发人员不使用多线程,因此线程同步也没必要了。.Net框架包括一个EventHandlerList来解决这两个性能问题,EventHandlerList是个委托列表,它针对添加和移除委托操作进行了优化,我们对TestControl3进行优化。

7、首先需要为自定义控件公开的每个事件都定义一个私有静态只读的键,由于是静态,在所有的TestControl3控件实例中共享,只占用一次内存。

protected static readonly object TestKey = new object(); 

8、需要将事件定义为属性,而不是字段。这些事件属性采用了与普通属性不同的语法,事件属性使用add和remove代替了get和set。与其他控件类似,TestControl3从Control类继承了一个EventHandlerList类型的Events属性。当客户端使用+=符号将委托添加到Test事件事件委托到调用列表中时,add方法将自动调用EventHandlerList类的AddHandler方法,并将事件键和客户端委托传递给它。

public event TestEventHandler3 Test
        {
            add { Events.AddHandler(TestKey, value); }
            remove { Events.RemoveHandler(TestKey, value); }
        }

 9、 最后需要在引发事件的方法中实现EventHandlerList。该方法使用事件键作为事件列表的索引,以便访问Test事件委托。

protected virtual void OnTest(TestEventArgs3 e)
        {
            TestEventHandler3 test = Events[TestKey] as TestEventHandler3;
            if (test != null)
            {
                test(this, e);
            }
        }

10、使用EventHandlerList类解决了我们提出的两个问题了。

代码下载地址:点击下载

本博客内容有些来源于网络或书籍如果侵害到你的权益,请及时联系我(hch458458@vip.qq.com)
版权归nethch所有,转载请注明出处!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值