用winform程序来了解委托和事件
一、浅谈委托
如果有个过winform 和webform 程序开发的小伙伴一定有个这样的感觉吧,点击Button直接就执行了那个方法,到此他是怎么实现了的呢,大家有考虑过没有?
回到正题,什么是委托呢?委托,我们可以把看着是一个作为方法参数的一个方法,为什么呢,因为委托可以作为作为方法的参数,而给委托赋的值都是方法。下面我举一个例
- /// <summary>
/// 定义的一个打招呼的委托- /// </summary>
- /// <param name="name"></param>
- public delegate void GreetingDelegate(string name);
- /// <summary>
- /// 中国人打招呼的类
- /// </summary>
- public class Chinese
- {
- public void ChineseGreeting(string name)
- {
- Console.Write("早上好--" + name);
- }
- }
- public class English
- {
- public void EnglishGreeting(string name)
- {
- Console.Write("Good Morning--" + name);
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- Chinese people1 = new Chinese();
- English people2 = new English();
- Greeting("欢大少", people1.ChineseGreeting);
- Console.Write("\n");
- Greeting("Master", people2.EnglishGreeting);
- Console.ReadKey();
- }
- private static void Greeting(string name,GreetingDelegate MakingGreeting )
- {
- MakingGreeting(name);
- }
- }
运行结果
当然,实质上委托是一个特殊的类,知识有限,只能讲到这儿了,
事件是什么呢,其实事件就是用event修饰后的委托,
- class Program
- {
- static void Main(string[] args)
- {
- Publishser pb = new Publishser();
- Subscriber sb = new Subscriber();
- //pb.NumberChange += sb.OnNumberChange;
- pb.NumberChange = sb.OnNumberChange;
- pb.DoSomething();
- pb.NumberChange(100);
- Console.ReadLine();
- }
- }
- /// <summary>
- /// 定义委托
- /// </summary>
- public delegate void NumberChangeEventHandler(int count);
- public class Publishser
- {
- private int count;
- public NumberChangeEventHandler NumberChange;
- //public event NumberChangeEventHandler NumberChange;
- public void DoSomething()
- {
- if(NumberChange!=null)
- {
- count++;
- NumberChange(count);
- }
- }
- }
- public class Subscriber
- {
- public void OnNumberChange(int count)
- {
- Console.WriteLine("Subscriber notified count ={0}", count);
- }
- }
上面的代码如果是定义普通的委托能够正常运行,但如果换成事件来的话变异不能通过,为什么呢?因为为了更好的封装性,实际是事件是一个私有变量,外部不是访问,如果用委托变量,外部能够调用委托,影响封装性,就像上面代码
- pb.NumberChange(100);,如果定义为事件,那么NumberChange只能通过内部方法DoSomething来调用。
事件只能通过+=来进行赋值,如果你反编译你可以看到事件里有两个方法 Add() 和Remove(),分别对应的是+=和-=。
二、winform程序click事件的原理
在form的构造函数中,我们能看到下面的代码
- /// <summary>
- /// 设计器支持所需的方法 - 不要
- /// 使用代码编辑器修改此方法的内容。
- /// </summary>
- private void InitializeComponent()
- {
- this.button1 = new System.Windows.Forms.Button();
- this.SuspendLayout();
- //
- // button1
- //
- this.button1.Location = new System.Drawing.Point(, );
- this.button1.Name = "button1";
- this.button1.Size = new System.Drawing.Size(, );
- this.button1.TabIndex = ;
- this.button1.Text = "button1";
- this.button1.UseVisualStyleBackColor = true;
- this.button1.Click += new System.EventHandler(this.button1_Click);
- //
- // Form1
- //
- this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(, );
- this.Controls.Add(this.button1);
- this.Name = "Form1";
- this.Text = "F1";
- this.ResumeLayout(false);
- }
我们发现对事件的添加 this.button1.Click += new System.EventHandler(this.button1_Click);
这个地方我们只是添加了事件,但这个事件是怎么触发的呢?我们进行调试
button的click的触发经过如下过程
三、模拟winform事件
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- namespace MonitorEvent
- {
- /// <summary>
- /// 定义委托
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- public delegate void MonitorEventHandler(object sender, EventArgs e);
- /// <summary>
- /// 时间数据类
- /// </summary>
- public class MsgEventArgs : EventArgs
- {
- /// <summary>
- /// 修改时间
- /// </summary>
- public DateTime ChanggeTime { get; set; }
- /// <summary>
- /// 提示信息
- /// </summary>
- public string ToSend { get; set; }
- public MsgEventArgs(DateTime changgeTime, string toSend)
- {
- this.ChanggeTime = changgeTime;
- this.ToSend = toSend;
- }
- }
- /// <summary>
- /// 事件订阅者
- /// </summary>
- public class MonitorText
- {
- public string name = "文本文档";
- //定义监控文本事件
- public event MonitorEventHandler MonitorEvent;
- //上次文件更新时间用于判断文件是否修改过
- private DateTime _lastWriteTime = File.GetLastWriteTime(@"C:\Users\Administrator\Desktop\1.txt");
- public MonitorText()
- {
- }
- // 文件更新调用
- protected virtual void OnTextChange(MsgEventArgs e)
- {
- if (MonitorEvent != null)
- {
- //不为空,处理事件
- MonitorEvent(this, e);
- }
- }
- //事件监听的方法
- public void BeginMonitor()
- {
- DateTime bCurrentTime;
- while (true)
- {
- bCurrentTime = File.GetLastWriteTime(@"C:\Users\Administrator\Desktop\1.txt");
- if (bCurrentTime != _lastWriteTime)
- {
- _lastWriteTime = bCurrentTime;
- MsgEventArgs msg = new MsgEventArgs(bCurrentTime, "文本改变了");
- OnTextChange(msg);
- }
- //0.1秒监控一次
- Thread.Sleep();
- }
- }
- }
- /// <summary>
- /// 事件监听者
- /// </summary>
- public class Administrator
- {
- //管理员事件处理方法
- public void OnTextChange(object Sender, EventArgs e)
- {
- MonitorText monitorText = (MonitorText)Sender;
- Console.WriteLine("尊敬的管理员:" + DateTime.Now.ToString() + ": " + monitorText.name + "发生改变.");
- }
- }
- class Program
- {
- static MonitorText MonitorTextEventSource;
- static void Main(string[] args)
- {
- MonitorTextEventSource = new MonitorText();
- //1. 启动后台线程添加监视事件
- var thrd = new Thread(MonitorTextEventSource.BeginMonitor);
- thrd.IsBackground = true;
- thrd.Start();
- //2实例化管理员类
- Administrator ad = new Administrator();
- //4订阅事件
- MonitorTextEventSource.MonitorEvent += ad.OnTextChange;
- Console.ReadLine();
- }
- }
- }
四、申明
文中的观点多来源与张子阳的.net之美和ATtuing的博客,希望大家共同学习
用winform程序来了解委托和事件的更多相关文章
- (.NET高级课程笔记)委托、事件总结
1.委托的声明.实例化和调用 同样的,也可以把事务写成上面的形式 2.泛型委托---Func.Action 3.委托的意义:解耦 4.委托的意义:异步多线程 5.委托的意义:多播委托 6.观察者模 ...
- C#委托和事件的使用的意义
转载自:https://www.cnblogs.com/yinqixin/p/5056307.html 每一个初学C#的程序猿,在刚刚碰到委托和事件的概念时,估计都是望而却步,茫然摸不到头脑的.百度一 ...
- 编写高质量代码改善C#程序的157个建议——建议137:委托和事件类型应添加上级后缀
建议137:委托和事件类型应添加上级后缀 委托类型本身是一个类,考虑让派生类的名字以基类名字作为后缀.事件类型是一类特殊的委托,所以事件类型也遵循本建议. 委托和事件的正确的命名方式有: public ...
- CS中委托与事件的使用-以Winform中跨窗体传值为例
场景 委托(Delegate) 委托是对存有某个方法的引用的一种引用类型变量. 委托特别用于实现事件和回调方法. 声明委托 public delegate int MyDelegate (string ...
- winform子窗口与父窗口的交互-使用委托与事件
实现子窗口与父窗口的交互,通过父窗口调用并控制子窗口,子窗口也能控制父窗口,使用委托和事件的方法,可以实现. 1.父窗口调用子窗口,并通过子窗口控制父窗口 新建工程,创建两个窗体 显示子窗体的代 ...
- winform使用委托和事件在窗体之间传值
定义委托和事件,并且触发这个事件 //定义委托 public delegate void ShowOutStockDelegate(List<OutStockResultDto> outS ...
- .NET面试题系列[7] - 委托与事件
委托和事件 委托在C#中具有无比重要的地位. C#中的委托可以说俯拾即是,从LINQ中的lambda表达式到(包括但不限于)winform,wpf中的各种事件都有着委托的身影.C#中如果没有了事件,那 ...
- C# 委托和事件 与 观察者模式(发布-订阅模式)讲解 by天命
使用面向对象的思想 用c#控制台代码模拟猫抓老鼠 我们先来分析一下猫抓老鼠的过程 1.猫叫了 2.所有老鼠听到叫声,知道是哪只猫来了 3.老鼠们逃跑,边逃边喊:"xx猫来了,快跑啊!我是老鼠 ...
- 从web页面启动winform程序的实现方法
本文实现的需求是: A.通过web页面启动winform程序: B.将页面的参数传递给winform程序: C.winform程序已经启动并正在运行时,从web页面不能重新启动winform程序,只是 ...
随机推荐
- 12月15日smarty模板基本语法
smarty基本语法: 1.注释:<{* this is a comment *}>,注意左右分隔符的写法,要和自己定义的一致. <{* I am a Smarty comment, ...
- [git] warning: LF will be replaced by CRLF | fatal: CRLF would be replaced by LF
遇到这两个错误,是因为Git的换行符检查功能. core.safecrlf Git提供了一个换行符检查功能(core.safecrlf),可以在提交时检查文件是否混用了不同风格的换行符.这个功能的选项 ...
- Java国际化(i18n)
Java国际化(i18n) 最近在做一个网站国际化的功能.用Java做开发,使用spring+velocity. Java提供了对i18n的支持,spring对其做了集成,可以很方便的配置.主要思想就 ...
- Python 简易聊天机器人
聊天机器人 | |-----MySql | |---module--"逻辑运算层" | | | |---ciku--"与词库交互" | | | |---dict ...
- android 弹出AlertDialog的学习案例
我在编写的时候,测试的关键代码: AlertDialog.Builder builder=new AlertDialog.Builder(MainPointListActivity.this); bu ...
- php使用openssl进行Rsa长数据加密(117)解密(128) 和 DES 加密解密
PHP使用openssl进行Rsa加密,如果要加密的明文太长则会出错,解决方法:加密的时候117个字符加密一次,然后把所有的密文拼接成一个密文:解密的时候需要128个字符解密一下,然后拼接成数据. 加 ...
- 深入理解 JavaScript 变量的作用域和作用域链
一个变量的作用域(scope)是程序源代码中定义这个变量的区域.简单的说,作用域就是变量与函数的可访问范围.全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义.局部变量是在函数体内 ...
- ORA-01033 ORACLE 正在初始化或关闭
(借鉴:该方法本人亲自操作过,解决了问题!) 解决连接ORACLE错误一例:ORA-01033: ORACLE 正在初始化或关闭 客户发现连接数据库有问题,错误有: ORA-01033: ORACLE ...
- hdu 4329
problem:http://acm.hdu.edu.cn/showproblem.php?pid=4329 题意:模拟 a. p(r)= R'/i rel(r)=(1||0) R ...
- php mysqli mysqli_query() mysqli_real_query()
2016年11月26日 15:22:27 星期六 场景: PHP从mysql中读取数据 1. 一次性读取所有数据返给PHP 2. 每次循环只读取一掉记录 数据量小的时候可以使用第一种方法, 数据量很大 ...