Event
一、概念
事件是被拥有者的内部逻辑触发的
事件处理器是事件响应者的一个成员
二、例子
一星
1 /*======================一星的例子=================*/ 2 using system; 3 using system.windows.Forms; 4 5 namespace EventExample 6 { 7 class Program 8 { 9 static void Main(string[] args) 10 { 11 Form form = new Form(); 12 Controller controller = new Controller(form); //事件的响应者 13 } 14 } 15 16 class Controller 17 { 18 private Form form; 19 public Controller ( Form form ) 20 { 21 if (form!=null) 22 { 23 this.form = form;//通过this区分哪个是我传进来的参数,哪个是我的字段 24 this.form.Click += this.FormClicked; 25 } 26 } 27 private void FormClicked(object sender , EventArgs e) 28 { 29 this.form.Text = DateTime.Now.ToString(); 30 } 31 } 32 33 34 }
两星
1 /*===================两星的组合方式=====================*/ 2 //事件的拥有者同时也是事件的响应者,一个对象拿着自己的方法订阅处理自己的事件 3 4 using system; 5 using system.windows.Forms; 6 7 namespace EventExample 8 { 9 class program 10 { 11 static void main(string[] args) 12 { 13 MyForm form = new MyForm(); 14 form.Click += form.FormClicked; 15 } 16 } 17 18 19 class MyForm : Form 20 { 21 internal void FormClicked(object sender , EventArgs e) 22 { 23 this.Text = datetime.now.tostring(); 24 25 } 26 27 } 28 29 }
三星
1 /*===================事件为三星=================*/ 2 //事件的拥有者是事件响应者的字段成员,事件的响应者用自己的方法订阅者自己成员的某个事件,而我们的事件响应者用自己的方法订阅着自己字段成员的某个事件 3 4 //在一个窗口里有一个文本框和一个按钮,点击按钮文本框显示hello world 5 using system; 6 using system.windows.Forms; 7 namespace EventExample 8 { 9 class Program 10 { 11 static void main(string[] args) 12 { 13 MyForm myform = new MyForm(); 14 form.showdialog(); 15 16 } 17 18 19 } 20 class MyForm:Form 21 { 22 private TextBox textbox; 23 private Button button; 24 25 public MyForm() 26 { 27 this.textbox = new TextBox(); 28 this.button = new Button(); 29 this.Controls.Add(this.button); //为让这两个控件显示在窗口里 30 this.Controls.Add(this.textBox); //为让这两个控件显示在窗口里 31 //能不能让textbox来响应这个事件呢,答案是不能的。因为textbox这个类也是微软给出来的 ,它不可能在改变了,不可能在为这个类添加事件处理器 32 33 this.button.Click += this.ButtonClicked; 34 35 } 36 private void ButtonClicked(object sender , EventArgs e) 37 { 38 this.textBox.Text = "Hello World"; 39 } 40 41 } 42 }
三、挂接事件处理的方法
1 using system;
2 using system.window.Forms;
3
4 namespace WinformExample
5 {
6 public class Form1:Form
7 {
8 public Form1()
9 /*=============//第一种挂接事件处理器的方法==========*/
10 this.button3.click += this.button.clicked; //第一种挂接事件处理器的方法
11
12 /*=============//第二种挂接事件处理器的方法==========*/
13 this.button3.click += (object sender,EventArgs e)=>(this.textBox1.text = "Hello"); //第二种挂接事件处理器的方法
14
15
16 }
17 private void ButtonClicked(object sender,EventArgs e)
18 {
19 if (sender == this.button1)
20 {this.textBox1.text = "hello";}
21
22 if (sender == this.button2)
23 {this.textBox1.text = "world";}
24
25 if (sender == this.button3)
26 {this.textBox1.text = "Mr.OKay";}
27
28 }
29 }
30
31 //一个事件可以挂接多个处理器,一个处理器可以被多个事件挂接
四、事件的声明
1.事件的完整声明
事件是基于委托的,有两层意思
第一层: 事件需要委托类型来做一个约束,约束既规定了事件能发送什么样的消息给事件的响应者,也规定了事件的响应者能收到什么样的消息。这就决定了事件响应者的事件处理器必须能和这个约束匹配上,才能订阅这个事件
第二层: 当事件的响应者向事件的拥有着提供了能够匹配这个事件的事件处理器之后,总得找个地方把这个事件处理器保存记录下来。而能够记录引用方法的任务也只有委托类型的实例才可以办到
1 /*===================事件的完整声明====================*/ 2 using System; 3 using System.Collections.Generic; 4 using System.Linq; 5 using System.Text; 6 using System.Threading; 7 using System.Threading.Tasks; 8 9 namespace EventExample1___02_33 //事件完整声明 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 Customer customer = new Customer(); 16 Waiter waiter = new Waiter(); 17 customer.Order += waiter.action; 18 customer.Action(); 19 customer.PayTheBill(); 20 Console.ReadLine(); 21 } 22 } 23 24 public class OrderEventArgs: EventArgs //传递事件信息的,事件信息术语叫做“EventArgs” 25 { 26 public string DishName { get; set; } 27 public string Size { get; set; } 28 } 29 30 31 32 public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//类库中没有哪个委托是为点菜这个事件准备的,只能自己声明 33 34 //委托是为了声明某个事件准备的,这个委托的名字应使用event handler作为后缀 35 //第一个参数表明是谁点的菜,第二个是表明我们点的菜的信息(能够用来存储我们菜的信息的数据类型还没有,我们要去声明这个数据类型) 36 //EventHandler: 37 //事件处理器的返回值类型是void 38 //约束事件处理器的 39 //这个委托未来创建的实例,是专门用于存储事件处理器的 40 41 42 43 public class Customer 44 { 45 private OrderEventHandler orderEventHandler;//这个委托字段用来存储引用事件处理的 46 public event OrderEventHandler Order //声明事件,拿哪个委托类型来约束这个事件呢,这边是OrderEventHandler 47 { 48 add //事件处理的添加器 49 { 50 this.orderEventHandler += value; 51 } 52 remove //事件处理器的移除器 53 { 54 this.orderEventHandler -= value; 55 } 56 } 57 public double Bill { get; set; } 58 public void PayTheBill() 59 { 60 Console.WriteLine("i will pay {0}", this.Bill); 61 } 62 63 public void WalkIn() 64 { 65 Console.WriteLine("Walk into the restaurant"); 66 } 67 public void SitDown() 68 { 69 Console.WriteLine("Sit down"); 70 } 71 72 public void Think() 73 { 74 for(int i = 0; i < 5; i++) 75 { 76 Console.WriteLine("let me think..."); 77 Thread.Sleep(1000); 78 } 79 if(this.orderEventHandler != null) 80 { 81 OrderEventArgs e = new OrderEventArgs(); 82 e.DishName = "kongpao chicken"; 83 e.Size = "large"; 84 this.orderEventHandler.Invoke(this, e);//第一个参数谁在点菜,第二个参数想点什么菜 85 } 86 } 87 public void Action() 88 { 89 Console.ReadLine(); 90 this.WalkIn(); 91 this.SitDown(); 92 this.Think(); 93 94 } 95 } 96 97 98 public class Waiter 99 { 100 public void action(Customer customer, OrderEventArgs e) 101 { 102 Console.WriteLine(" i will serve you the dish{0}", e.DishName); 103 double price = 10; 104 switch (e.Size) 105 { 106 case "small": 107 price = price * 0.5; 108 break; 109 case "large": 110 price = price * 1.5; 111 break; 112 default: 113 break; 114 } 115 customer.Bill += price; 116 117 } 118 } 119 120 }
2.事件的简略声明
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace EventExample1___29_11 //事件的简化声明 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 Customer customer = new Customer(); 15 Waiter waiter = new Waiter(); 16 customer.Order += waiter.action; 17 customer.Action(); 18 customer.PayTheBill(); 19 Console.ReadLine(); 20 } 21 } 22 23 public class OrderEventArgs : EventArgs //传递事件信息的,事件信息术语叫做“EventArgs” 24 { 25 public string DishName { get; set; } 26 public string Size { get; set; } 27 } 28 29 30 31 public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//类库中没有哪个委托是为点菜这个事件准备的,只能自己声明 32 //委托是为了声明某个事件准备的,这个委托的名字应使用event handler作为后缀 33 //第一个参数表明是谁点的菜,第二个是表明我们点的菜的信息(能够用来存储我们菜的信息的数据类型还没有,我们要去声明这个数据类型) 34 35 36 37 38 public class Customer 39 { 40 public event OrderEventHandler Order;//事件的简化声明 41 public double Bill { get; set; } 42 public void PayTheBill() 43 { 44 Console.WriteLine("i will pay {0}", this.Bill); 45 } 46 47 public void WalkIn() 48 { 49 Console.WriteLine("Walk into the restaurant"); 50 } 51 public void SitDown() 52 { 53 Console.WriteLine("Sit down"); 54 } 55 56 public void Think() 57 { 58 for (int i = 0; i < 5; i++) 59 { 60 Console.WriteLine("let me think..."); 61 Thread.Sleep(1000); 62 } 63 if (this.Order != null) //使用事件的名字做判断 取代this.orderEventHandler != null 64 { 65 OrderEventArgs e = new OrderEventArgs(); 66 e.DishName = "kongpao chicken"; 67 e.Size = "large"; 68 this.Order.Invoke(this, e);//第一个参数谁在点菜,第二个参数想点什么菜 取代this.orderEventHandler.Invoke(this, e) 69 } 70 } 71 public void Action() 72 { 73 Console.ReadLine(); 74 this.WalkIn(); 75 this.SitDown(); 76 this.Think(); 77 78 } 79 } 80 81 82 public class Waiter 83 { 84 public void action(Customer customer, OrderEventArgs e) 85 { 86 Console.WriteLine(" i will serve you the dish{0}", e.DishName); 87 double price = 10; 88 switch (e.Size) 89 { 90 case "small": 91 price = price * 0.5; 92 break; 93 case "large": 94 price = price * 1.5; 95 break; 96 default: 97 break; 98 } 99 customer.Bill += price; 100 101 } 102 } 103 104 }
3.EventHandler学习和使用
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading; 6 using System.Threading.Tasks; 7 8 namespace EventExample1___29_11 //事件的简化声明 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 Customer customer = new Customer(); 15 Waiter waiter = new Waiter(); 16 customer.Order += waiter.action; 17 customer.Action(); 18 customer.PayTheBill(); 19 Console.ReadLine(); 20 } 21 } 22 23 public class OrderEventArgs : EventArgs //传递事件信息的,事件信息术语叫做“EventArgs” 24 { 25 public string DishName { get; set; } 26 public string Size { get; set; } 27 } 28 29 30 /*===使用donet平台为我们准备好的eventhandler,下面的委托没有必要==*/ 31 // public delegate void OrderEventHandler(Customer customer, OrderEventArgs e); 32 33 34 35 36 public class Customer 37 { 38 /*====将public event OrderEventHandler Order修改为 public event EventHandler Order; ==================*/ 39 40 // public event OrderEventHandler Order;//事件的简化声明 41 public event EventHandler Order;//事件的简化声明 42 /*=====可以去看EventHandler的定义 public delegate void EventHandler(object sender,EventArgs);==================*/ 43 44 45 public double Bill { get; set; } 46 public void PayTheBill() 47 { 48 Console.WriteLine("i will pay {0}", this.Bill); 49 } 50 51 public void WalkIn() 52 { 53 Console.WriteLine("Walk into the restaurant"); 54 } 55 public void SitDown() 56 { 57 Console.WriteLine("Sit down"); 58 } 59 60 public void Think() 61 { 62 for (int i = 0; i < 5; i++) 63 { 64 Console.WriteLine("let me think..."); 65 Thread.Sleep(1000); 66 } 67 if (this.Order != null) //使用事件的名字做判断 取代this.orderEventHandler != null 68 { 69 OrderEventArgs e = new OrderEventArgs(); 70 e.DishName = "kongpao chicken"; 71 e.Size = "large"; 72 this.Order.Invoke(this, e);//第一个参数谁在点菜,第二个参数想点什么菜 取代this.orderEventHandler.Invoke(this, e) 73 } 74 } 75 public void Action() 76 { 77 Console.ReadLine(); 78 this.WalkIn(); 79 this.SitDown(); 80 this.Think(); 81 82 } 83 } 84 85 86 public class Waiter 87 { 88 89 /*========将 public void action(Customer customer, OrderEventArgs e)修改为 public void action(object customer, EventArgs e)=======*/ 90 91 92 // public void action(Customer customer, OrderEventArgs e) 93 public void action(Object customer, EventArgs e) 94 { 95 96 /*===传进来的object没有Bill这个属性,传进来的e没有DishName和Size这两 个属性=========需要做一个类型转换 Customer customer = sender as Customer; OrderEventArgs orderinfo = e as OrderEventArgs;========*/ 97 98 Customer customer = sender as Customer; 99 OrderEventArgs orderinfo = e as OrderEventArgs; 100 101 102 Console.WriteLine(" i will serve you the dish{0}", orderinfo.DishName); 103 double price = 10; 104 switch (orderinfo.Size) 105 { 106 case "small": 107 price = price * 0.5; 108 break; 109 case "large": 110 price = price * 1.5; 111 break; 112 default: 113 break; 114 } 115 customer.Bill += price; 116 117 } 118 } 119 120 }