51Halcon机器视觉

 找回密码
 会员注册

QQ登录

只需一步,快速开始

扫一扫,微信登录

查看: 2817|回复: 6

[资料] C#事件处理的简单实例(转)

[复制链接]
  • TA的每日心情
    振奋
    昨天 10:07
  • 签到天数: 679 天

    连续签到: 1 天

    [LV.9]以坛为家II

    147

    主题

    757

    帖子

    4478

    积分

    Rank: 9

    积分
    4478

    热心会员突出贡献切换助手验证会员最佳新人

    发表于 2016-6-20 14:58:49 | 显示全部楼层 |阅读模式

    51Halcon诚邀您的加入,专注于机器视觉开发与应用技术,我们一直都在努力!

    您需要 登录 才可以下载或查看,没有帐号?会员注册

    x
    本帖最后由 bbyy 于 2016-6-20 14:59 编辑

    【内容提要】本文讨论了C#含事件的类的设计方法和使用方法。通过一个实例详细解剖了事件、代理、事件处理的基本的概念。也许对初学C#的人员会有一定的帮助。

    一、C#的事件处理涉及到的内容

    1、用户事件参数的定义(从EventArgs派生)

    2、delegate的定义

    3、event的定义

    4、事件唤醒方法即On方法

    5、用户事件处理方法

    编写含有事件的类实际上只需要前四项内容,最后一项是应用该类的用户来编写的。

    如果无用户参数,则不需定义1和2两项,直接使用系统提供的EventArgs和EventHandler即可。这时从3开始定义:

    事件的定义:

    public  event  void  EventHandler   MyHandler;

    On事件唤醒方法就是:

    protected  virtual   void   OnMyHandler (  EventArgs   e  )

    {

            if (MyHandler != null)

                  MyHandler( this, e );

    }

    本文要探讨的是完整的事件处理过程,所以事件参数自己定义。详见下例。

    二、实例

    我们通过一个实例来看如何实现事件处理的完整过程

    要求:编写一个Person类

    1、含有name字段用于存储名字,含有age字段存储年龄,同时设置两个属性Name和Age分别实现对name和age的获取和设置。

    2、修改age字段后会触发一个事件AgeChanged,由用户决定修改age后如何操作,用户能够通过事件参数获得修改之前的age的值。

    3、编写Person类的应用程序:一种是直接使用Person,另一种是从Person派生一个Student类,并分别给出相应的事件处理的方法

    三、具体步骤

    1、定义事件参数PersonEventArgs (如果你的类无需事件参数可不定义,直接用系统提供的EventArgs就可以了,本例中要求在事件处理方法中通过参数PersonEventArgs  e 获得修改之前的年龄,所以必须定义新的事件参数)

        public class PersonEventArgs:EventArgs

        {

            private int oldage;         //修改之前的年龄

            public int OldAge

            {

                get { return oldage; }

            }

            public PersonEventArgs( int age )

            {

                this.oldage = age;

            }

        }

    2、定义代理PersonHandler

        public delegate void PersonHandler(object sender, PersonEventArgs e);

    如果没有用户自定义的事件参数,那么可以不定义用户自己的代理,直接使用System的EventHandler即可。

    3、定义Person类(这是一个含事件的类),事件AgeChanged被定义在该类中(需要说明的是上述PersonEventArgs和PersonHandler都可以定义在Person类中)

        public class Person

        {

          

            private string name;                   //姓名

            private int age;                       //年龄



            //定义事件:当年龄被改变之后触发

            public event PersonHandler AgeChanged;

            //这是事件唤醒方法:按dotnet规范被定义为protected  virtual

            protected virtual void OnAgeChanged( PersonEventArgs e )

            {

                if (AgeChanged != null)

                    AgeChanged( this, e );

            }

           //这是名字属性

            public string Name

            {

                get { return name; }

                set { name = value; }

            }

            //这是年龄属性:年龄改变时要触发AgeChanged事件,由于是改变后触发所以On放在了最后

            public int Age

            {

                get { return age; }

                set

                {

                    if (age != value)

                    {

                        int age0 = age;

                        age = value;

                      OnAgeChanged(new PersonEventArgs(age0));

                    }

                }

            }

            //这是年龄增加的方法:注意要触发AgeChanged事件

            public void AddAge(int offset)

            {

                if (offset != 0)

                {

                    int age0 = age;

                    age += offset;

                    OnAgeChanged( new PersonEventArgs(age0) );

                }

            }

            public override string ToString()

            {

                return string.Format ("Name:{0}\tAge:{1}\t",name ,age );

            }

            public Person()

            {

                name = "";

                age = 0;

            }

            public Person(string name,int age)

            {

                this.name = name;

                this.age = age;

            }

        }



    4、应用Person类

       <方法一>直接使用Person类

        class Program

        {

            static void Main(string[] args)

            {

                Person p = new Person("李四",20);

                Console.WriteLine(p.ToString());

                //向事件代理指定用户的事件处理方法

              p.AgeChanged += new PersonHandler(Person_AgeChanged);

                p.AddAge(60); //修改了年龄,要触发AgeChanged事件

                Console.WriteLine(p.ToString());

                Console.Read();

            }

    //这是用户的事件处理方法

            protected static void Person_AgeChanged(object sender,PersonEventArgs e)

            {

                 //用户在此添加代码实现用户要求

                Console.WriteLine("修改前的年龄是:{0}",e.OldAge );

            }

        }

    运行结果如下:

        Name:李四       Age:20

        修改前的年龄是:20

        Name:李四       Age:80



    注意:用这种方法使用Person不能用其OnAgeChange这个事件唤醒方法,因为它在Person中被定义为protected virtual。如果定义为public virtual 就可了,但是从.net 定义的事件看所有的事件唤醒On方法都是定义成protected virtual的。所以本文不讨论public virtual型的On事件唤醒方法。

       <方法二>从Person派生新类:只使用其OnAgeChanged 而不用用户的事件处理方法,实际上就是用OnAgeChange作为用户的事件处理方法了。

    设计一个类Student,增加一个字段年级grade,并设置一个属性Grade获取和设置grade的值。同样当修改学生的年龄时要触发AgeChanged事件。

      public class Student:Person

        {

            private string grade;   //班级

            public string Grade

            {

                get { return grade; }

                set { grade = value; }

            }

            public override string  ToString()

            {

              return base.ToString()+ "Grade:" + grade ;

            }

            //由于不编写用户的单独的事件处理方法,所以直接使用On方法来实现用户的事件处理

            protected override void OnAgeChanged( PersonEventArgs e )

            {

       //用户添加代码,实现用户要求

                Console.WriteLine("修改了年龄:修改前的年龄是 {0},修改后的年龄是 {1}",  e.OldAge, Age);

            }

           //这是另一个可能触发AgeChanged事件的方法:重新设置对象

            public void Set(string name, int age, string grade)

            {

                Name = name;

                Age = age;   //特别注意:只有改变属性Age才可能触发AgeChanged事件。

                this.grade = grade;

            }

            public Student(string name,int age,string grade):base(name ,age )

            {

                this.grade = grade;

            }

        }

    测试程序如下:

       using  System;

       class Program

       {

            static void Main(string[] args)

            {

                Student st = new Student("张三",50,"高二23班");

                Console.WriteLine(st.ToString ());

                st.Age = 60;      //修改年龄,要触发AgeChanged事件

                Console.WriteLine(st.ToString());

                st.AddAge(30);    //增加年龄,要触发AgeChanged事件

                Console.WriteLine(st.ToString());

                Console.Read();

            }

        }

    运行结果如下:

        Name:张三       Age:50  Grade:高二23班

        修改了年龄:修改前的年龄是 50,修改后的年龄是 60

        Name:张三       Age:60  Grade:高二23班

        修改了年龄:修改前的年龄是 60,修改后的年龄是 90

        Name:张三       Age:90  Grade:高二23班

    注意:用户要想在年龄被修改后做点什么,那么就直接在Student的OnAgeChanged中进行相应的编码就可以了。

       <方法三>从Person派生新类:不直接使用OnAgeChanged而用代理方法

    例子同<方法二>

         public class Student:Person

        {

            private string grade;   //班级

            public string Grade

            {

                get { return grade; }

                set { grade = value; }

            }

            public override string  ToString()

            {

              return base.ToString()+ "Grade:" + grade ;

            }

           //用户的事件处理方法

        protected  void  Person_AgeChanged ( object sender , PersonEventArgs e)

       {

            //用户自己添加代码,实现用户的要求   

                Console.WriteLine("修改了年龄:修改前的年龄是 {0},修改后的年龄是 {1}",  e.OldAge, Age);

       }

            public void Set(string name, int age, string grade)

            {

                Name = name;

                Age = age;

                this.grade = grade;

            }

            public Student(string name,int age,string grade):base(name ,age )

            {

           //使用用户的事件处理方法时必须使事件AgeChanged 指向用户事件处理方法

           AgeChanged += new  PersonHandler(Person_AgeChanged );

                this.grade = grade;

            }

        }

    }

    测试程序同上,结果同上。

    需要说明的是上述测试程序要想正确运行应该在每个类定义前加上一行:

    using  System;

    四、总结

    通过上述实例我们清楚的了解了C#事件的处理过程和如何设计含有事件的类及其使用方法。





                

    1.发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

    2.提问请组织好自己的逻辑,标题注明大概是什么问题,问题内容写详细,需提供问题症状、错误代码、截图、位置等等信息,不要让别人去猜你想问啥;

    3.如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题前面加上【已解决】

    4.回报帮助你解决问题的坛友,右下角【免费评分】赠与对方视觉币和热心值,伸手党遭人唾弃,做一个热心并受欢迎的人!

  • TA的每日心情
    点赞
    2020-4-11 22:34
  • 签到天数: 117 天

    连续签到: 1 天

    [LV.6]常住居民II

    3

    主题

    56

    帖子

    708

    积分

    Rank: 3

    积分
    708

    切换助手验证会员

    发表于 2016-12-8 10:53:39 | 显示全部楼层

    RE: C#事件处理的简单实例(转)

    :D楼主讲的很详细 受教了

    1.发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

    2.提问请组织好自己的逻辑,标题注明大概是什么问题,问题内容写详细,需提供问题症状、错误代码、截图、位置等等信息,不要让别人去猜你想问啥;

    3.如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题前面加上【已解决】

    4.回报帮助你解决问题的坛友,右下角【免费评分】赠与对方视觉币和热心值,伸手党遭人唾弃,做一个热心并受欢迎的人!

  • TA的每日心情
    窃喜
    2020-5-30 09:37
  • 签到天数: 30 天

    连续签到: 1 天

    [LV.5]常住居民I

    0

    主题

    65

    帖子

    151

    积分

    Rank: 1

    积分
    151
    发表于 2017-10-23 20:58:19 | 显示全部楼层
    路过 分享 希望以后用得上!

    1.发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

    2.提问请组织好自己的逻辑,标题注明大概是什么问题,问题内容写详细,需提供问题症状、错误代码、截图、位置等等信息,不要让别人去猜你想问啥;

    3.如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题前面加上【已解决】

    4.回报帮助你解决问题的坛友,右下角【免费评分】赠与对方视觉币和热心值,伸手党遭人唾弃,做一个热心并受欢迎的人!

  • TA的每日心情
    害羞
    2018-3-7 14:29
  • 签到天数: 18 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    3

    主题

    71

    帖子

    153

    积分

    Rank: 2Rank: 2

    积分
    153
    发表于 2017-11-4 11:25:14 | 显示全部楼层

    新手过来学习学习

    1.发帖求助前要善用论坛搜索功能,那里可能会有你要找的答案;

    2.提问请组织好自己的逻辑,标题注明大概是什么问题,问题内容写详细,需提供问题症状、错误代码、截图、位置等等信息,不要让别人去猜你想问啥;

    3.如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子分类或者标题前面加上【已解决】

    4.回报帮助你解决问题的坛友,右下角【免费评分】赠与对方视觉币和热心值,伸手党遭人唾弃,做一个热心并受欢迎的人!

    您需要登录后才可以回帖 会员登录 | 会员注册

    本版积分规则

    建议您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流浏览器浏览本网站

    51Halcon会员技术交流会员技术交流 | 51Halcon官方客服咨询官方客服咨询 | Halcon切换助手使用反馈切换助手使用

    有问题需要咨询站长?| 申请友链| 小黑屋| 手机版| Archiver|  

    粤ICP备15095995号-2 粤公网安备44030602000670号

    CopyRight © 2015-2020 51Halcon机器视觉. Tencent Cloud X3.4.

    快速回复 返回顶部 返回列表