• 关于C#中的自定义事件生成


    关于C#中的自定义事件生成:

    目标:通过一个实例来按步骤说明C#中如何创建,引发,接收和取消事件。例子是一个窗体程序,一个按钮和一个标签,点击按钮的时候就触发一个事件得到当前时间,如果秒是后30秒就输出一个Wasn't a right time!!


    一,创建一个事件类型:

    1,新建一个窗体应用程序,添加一个button和lebelInfo,name分别为buttonRaise和labelInfo。

    2,定义一个委托:
    在窗体类的声明部分添加,
    public delegate void ActionEventHandler(object sender, ActionCancelEventArgs e);
    这里我们声明了一个新的委托类型ActionEventHandler,原因是我们后面要自己定制EventArg类(上面可见就是ActionCancelEventArgs类),方法名必须和委托匹配。

    3,定义一个事件:
    在上面代码后面加上,
    public static event ActionEventHandler Action;
    我们定义了一个叫Action的事件,事件定义的语法要求指定与事件相关的委托。

    4,创建自己定义的EventArg类:
    在程序中定义一个类代码如下:
    namespace WindowsApplication1
    {
       public class ActionCancelEventArgs : System.ComponentModel.CancelEventArgs
       {
          string message = String.Empty;

          public ActionCancelEventArgs() : base() { }

          public ActionCancelEventArgs(bool cancel) : base(cancel) { }

          public ActionCancelEventArgs(bool cancel, string message)
             : base(cancel)
          {
             this.message = message;
          }

          public string Message
          {
             get { return message; }
             set { message = value; }
          }
       }
    }
    这个新类ActionCancelEventArgs实际上派生于CancelEventArgs,而CancelEventArgs派生于EventArgs。CancelEventArgs添加了Cancel属性,是一个bool类型,它通知sender对象,接收器希望取消或者停止事件的处理。我们为ActionCancelEventArgs添加一个message属性,包含事件处理时候传递一个事件处理状态的字符串。
    所有的基于EventArgs的类都负责在发送器和接收器之间来回传送事件的信息。大多情况下,EventArgs类中使用的信息都被事件处理程序中的接收器对象(这里后来的ActionCancelEventArgs ev)所使用。但是有时候,事件处理程序可以把信息添加到EventArg类中,使之可以用于发送器。我们这里就是这样做的其实(接收器根据状态把信息传给发送器中的message属性了)。


    二,引发事件:

    1,通过一种动作来激活Action事件(我们就用点击按钮buttonRaise):
    先为buttonRaise按钮添加一个点击事件处理程序:
    private void buttonRaise_Click(object sender, EventArgs e)

    2,再在处理程序中用正确的参数调用事件:添加如下代码,
    ActionCancelEventArgs cancelEvent = new ActionCancelEventArgs();
    OnAction(this, cancelEvent);

    就是先创建一个新的事件数据类型ActionCancelEventArgs,再把它当作参数传递给前面定义的那个Action事件的处理程序(引发事件是通过Action(this, cancelEvent)的,但是我们通过OnAction()来调用之)。这里我们的Action事件就相当我们.Net中的Move,Click事件一样的了,但是目前它还是空的,如果引发了这个事件就会产生一个空引用异常,所以我们如果在其他的类中把Action事件定义为基事件,则只要引发了Action就要定义相关的事件处理程序的。

    3,我们定义一个叫OnAction的函数引发事件,(加上On是命名约定)
    protected void OnAction(object sender, ActionCancelEventArgs e)
    {
        if (Action != null)    //捕获空引用错误
            Action(sender, e);
    }
    如果派生一个包含该方法和事件的新类,就必须重写OnAction方法,并且在重写代码中调用base.OnAction(),引发此事件。

    三,接受事件,并且处理之:
    1,下面就是定义一个新类BusEntity了:
    namespace WindowsApplication1
    {
       public class BusEntity
       {
          string time = String.Empty;

          public BusEntity()
          {
             Form1.Action += new Form1.ActionEventHandler(Form1_Action);
          }

          private void Form1_Action(object sender, ActionCancelEventArgs e)
          {
             e.Cancel = !DoActions();
             if (e.Cancel)
                e.Message = "Wasn't the right time.";
          }

          private bool DoActions()
          {
             bool retVal = false;
             DateTime tm = DateTime.Now;

             if (tm.Second < 30)
             {
                time = "The time is " + DateTime.Now.ToLongTimeString();
                retVal = true;
             }
             else
                time = "";

             return retVal;
          }

          public string TimeString
          {
             get { return time; }
          }
       }
    }
    其中关键代码:
    1,构造函数中声明了Form1.Action事件的处理程序(注册事件):
    Form1.Action += new Form1.ActionEventHandler(Form1_Action);
    注意这里注册的是Form1中定义的那个Action事件,不是其它地方定义的。

    2,Action事件的处理程序(在前面Form1类中通过OnAction()引发的):
    private void Form1_Action(object sender, ActionCancelEventArgs e)
    其中的处理是通过调用DoAction函数来的。它返回一个bool值,并且将状态信息赋值给事件数据类型ActionCancelEventArgs的参数的message成员。

    3,完善Form1程序:
    (1),类中要先新建成员private BusEntity busEntity;
    (2),构造函数中初始化之:busEntity = new BusEntity();
    (3),完善点击按钮的事件处理,引发并且处理Action事件:
    private void buttonRaise_Click(object sender, EventArgs e)
    {
        ActionCancelEventArgs cancelEvent = new ActionCancelEventArgs();
        OnAction(this, cancelEvent);
        if (cancelEvent.Cancel)
            labelInfo.Text = cancelEvent.Message;
        else
            labelInfo.Text = busEntity.TimeString;
    }
    在补充说明:这里创建了ActionCancelEventArgs对象,接着引发了Action事件,并且传递了新建的ActionCancelEventArgs对象cancelEvent。在调用OnAction方法,引发事件的时候,BusEntity对象中Action事件处理程序的代码就会执行。如果还有其他对象注册了事件,它们同样会执行。记住:如果其他对象也处理了事件Action,它们也会看到同一个ActionCancelEventArgs对象。如果需要确定是哪个对象取消了事件,而且如果多个对象取消了事件,就要在ActionCancelEventArgs类中再包含某种基于列表的数据结构。


    四,取消事件:
    在与委托一起注册的处理程序执行完之后,就可以查询ActionCancelEventArgs对象,并且确定它是否被取消了。也就是下面代码:
    if (cancelEvent.Cancel)
        labelInfo.Text = cancelEvent.Message;
    else
        labelInfo.Text = busEntity.TimeString
    ;


    总结:上面就是我个人通过《Professional C# 2005 with .Net 3.0》一书中的相关部分,总结出的如何利用事件和事件中基于EventArgs的对象,在应用程序中传递信息的。程序示例来源于此教程。

                                                                        Copyright © 2009 lcswr1987.CCBB. All Rights Reserved.

    转帖请标明出处http://hi.baidu.com/lcswr/blog/item/9ba59063c08890670d33fa05.html

  • 相关阅读:
    列出python中可变数据类型和不可变数据类型,并简述原理
    python 字典操作
    Python的is和==
    python2和python3区别
    下面的代码在Python2中的输出是什么?解释你的答案
    编程用sort进行排序,然后从最后一个元素开始判断,去重
    如何在一个function里面设置一个全局的变量?
    用Python匹配HTML tag的时候,<.>和<.?>有什么区别?
    请写出一段Python代码实现删除一个list里面的重复元素
    什么是lambda函数?它有什么好处?
  • 原文地址:https://www.cnblogs.com/CCBB/p/1443425.html
Copyright © 2020-2023  润新知