什么是事件
- 事件是类的成员
- 统一:
- 设计模式:事件模式
事件的应用
事件不会主动发生,由拥有者的内部的某个逻辑触发,才会发生通知
点击事件:是靠点击时是鼠标向硬件发送的电信号,windows还会记录按钮被按下的状态,松开时被绘制成松开的状态,而且被记录。如果有其他对象订阅了点击事件,这些事件的响应者就可以开始工作了。即,我们的程序在事件的驱动下开始运行了。
例案
这里的就是事件成员
案例1:认识订阅事件
using System;
using System.Collections.Generic;
using System.Timers;
//using System.Windows.Forms;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
Timer timer = new Timer();//timer就是事件的拥有者
timer.Interval = 1000;
Boy boy = new Boy();//boy是事件的响应者
timer.Elapsed += boy.Action;//+=是订阅事件,左边Elapsed是事件,右边要跟上事件响应者的事件处理器
timer.Start();
Console.ReadLine();
}
class Boy//事件处理器
{
internal void Action(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Jump!");
}
}
}
}
事件组合二
using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
Form form = new Form();//事件的拥有者
Controller controller = new Controller(form);//事件的响应者
form.ShowDialog();
}
static bool Test(List<int>intList)
{
foreach (var item in intList)
{
if (item<=10)
{
return false;
}
}
return true;
}
class Controller
{
private Form form;
public Controller(Form form)
{
if (form!=null)
{
this.form = form;//左边实例字段,右边是参数
this.form.Click += this.FormClicked;//+=左边订阅事件,右边是事件处理器,具体见方法,整个语句是事件订阅者
//「this」 就是Controller这个类的实例
}
}
private void FormClicked(object sender, EventArgs e)
{
this.form.Text=DateTime.Now.ToString();
}
}
}
}
事件组合三
using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
MyForm myform = new MyForm();//事件的拥有者
myform.Click += myform.FormClicked;
//Click是事件
myform.ShowDialog();
}
class MyForm:Form
{
internal void FormClicked(object sender, EventArgs e)
{
this.Text = DateTime.Now.ToString();
}
}
}
}
应用广泛
-
事件拥有者是事件响应者的一个字段成员
-
事件响应者用方法订阅着成员的某个事件
第三种挂接方式:委托匿名方法
lamda挂接
事件的声明
事件是基于委托的
- 事件需要一个委托事件来作为约束,这个约束既规定了事件能够发送什么消息给事件的响应者,也规定了事件的响应者能收到什么样的事件消息,这也就规定了事件响应者的事件处理器必须跟这个约束匹配上
- 当事件的响应者为事件的拥有者提供了能够匹配这个事件的事件处理器之后,需要一个地方保存和记录事件处理,这个地方就是委托的实例
准备一个委托,这个委托既能够事件相应的处理器必须跟时间匹配上才能完成订阅
事件委托的关系
原始声明
using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer();
Waiter waiter = new Waiter();
customer.Order += waiter.Action;
customer.Action();
customer.PayTheBill();
}
}
public class OrderEventArgs : EventArgs
{
public string DishName { get; set; }
public string Size { get; set; }
}
public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//当缺少类型时,自己去创建,记住这是为事件准备的委托,所以类型是EventArgs
public class Customer//事件拥有者
{
private OrderEventHandler orderEventHandler;//用于存储或者引用事件处理器的
public double Bill { get; set; }
public event OrderEventHandler Order//声明事件
{
add
{
this.orderEventHandler += value;//事件添加器
}
remove
{
this.orderEventHandler -= value;//事件移出器
}
}
public void PayTheBill()
{
Console.WriteLine("I will pay ${0}", this.Bill);
}
//声明点菜事件
public void Walkin()
{
Console.WriteLine("Walk into the restaurant");
}
public void SitDown()
{
Console.WriteLine("Sit down.");
}
public void Think()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Let me think...");
Thread.Sleep(1000);
}
if (this.orderEventHandler != null)
{
OrderEventArgs e = new OrderEventArgs();
e.DishName = "Kongpao CHichen";
e.Size = "large";
this.orderEventHandler.Invoke(this, e);
}
}
public void Action()
{
Console.ReadLine();
this.Walkin();
this.SitDown();
this.Think();
}
}
public class Waiter
{
internal void Action(Customer customer, OrderEventArgs e)
{
Console.WriteLine("I will serve you the dish-{0}", e.DishName);
double price = 10;
switch (e.Size)
{
case "small":
price = price * 05;
break;
case "large":
price = price * 1.5;
break;
default:
break;
}
customer.Bill = +price;
}
}
}
打印结果为
Walk into the restaurant
Sit down.
Let me think...
Let me think...
Let me think...
Let me think...
Let me think...
I will serve you the dish-Kongpao CHichen
I will pay $15
请按任意键继续. .
想5秒以后就出发了order事件,而waiter用action订阅了事件,那就开始执行了
简略格式声明
private OrderEventHandler orderEventHandler;
public event OrderEventHandler Order//声明事件
{
add
{
this.orderEventHandler += value;//事件添加器
}
remove
{
this.orderEventHandler -= value;//事件移出器
}
}
把37行的代码改为public event OrderEventHandler Order;
if (this.Order != null)
{
OrderEventArgs e = new OrderEventArgs();
e.DishName = "Kongpao CHichen";
e.Size = "large";
this.Order.Invoke(this, e);
}
跟着改变
完整简略声明代码
using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer();
Waiter waiter = new Waiter();
customer.Order += waiter.Action;
customer.Action();
customer.PayTheBill();
}
}
public class OrderEventArgs : EventArgs
{
public string DishName { get; set; }
public string Size { get; set; }
}
public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//当缺少类型时,自己去创建,记住这是为事件准备的委托,所以类型是EventArgs
public class Customer//事件拥有者
{
//用于存储或者引用事件处理器的
public double Bill { get; set; }
public event OrderEventHandler Order;//声明事件
public void PayTheBill()
{
Console.WriteLine("I will pay ${0}", this.Bill);
}
//声明点菜事件
public void Walkin()
{
Console.WriteLine("Walk into the restaurant");
}
public void SitDown()
{
Console.WriteLine("Sit down.");
}
public void Think()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Let me think...");
Thread.Sleep(1000);
}
if (this.Order != null)
{
OrderEventArgs e = new OrderEventArgs();
e.DishName = "Kongpao CHichen";
e.Size = "large";
this.Order.Invoke(this, e);
}
}
public void Action()
{
Console.ReadLine();
this.Walkin();
this.SitDown();
this.Think();
}
}
public class Waiter
{
internal void Action(Customer customer, OrderEventArgs e)
{
Console.WriteLine("I will serve you the dish-{0}", e.DishName);
double price = 10;
switch (e.Size)
{
case "small":
price = price * 05;
break;
case "large":
price = price * 1.5;
break;
default:
break;
}
customer.Bill = +price;
}
}
}
为什么要有事件
如果把委托的事件,改为字段。
using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
Console.ReadLine();
Customer customer = new Customer();
Waiter waiter = new Waiter();
customer.Order += waiter.Action;//这个时候,Order已经变成了字段
//customer.Action();
//customer.PayTheBill();
OrderEventArgs e = new OrderEventArgs();
e.DishName = "M";
e.Size = "large";
OrderEventArgs e2 = new OrderEventArgs();
e2.DishName = "B";
e2.Size = "large";
Customer badGuy = new Customer();
badGuy.Order += waiter.Action;
badGuy.Order.Invoke(customer,e);
badGuy.Order.Invoke(customer, e2);
customer.PayTheBill();
}
}
public class OrderEventArgs : EventArgs
{
public string DishName { get; set; }
public string Size { get; set; }
}
public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//当缺少类型时,自己去创建,记住这是为事件准备的委托,所以类型是EventArgs
public class Customer//事件拥有者
{
//用于存储或者引用事件处理器的
public double Bill { get; set; }
public OrderEventHandler Order;
public void PayTheBill()
{
Console.WriteLine("I will pay ${0}", this.Bill);
}
//声明点菜事件
public void Walkin()
{
Console.WriteLine("Walk into the restaurant");
}
public void SitDown()
{
Console.WriteLine("Sit down.");
}
public void Think()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Let me think...");
Thread.Sleep(1000);
}
if (this.Order != null)
{
OrderEventArgs e = new OrderEventArgs();
e.DishName = "Kongpao CHichen";
e.Size = "large";
this.Order.Invoke(this, e);
}
}
public void Action()
{
Console.ReadLine();
this.Walkin();
this.SitDown();
this.Think();
}
}
public class Waiter
{
internal void Action(Customer customer, OrderEventArgs e)
{
Console.WriteLine("I will serve you the dish-{0}", e.DishName);
double price = 10;
switch (e.Size)
{
case "small":
price = price * 05;
break;
case "large":
price = price * 1.5;
break;
default:
break;
}
customer.Bill +=price;
}
}
}
跟指针很像,会变得很乱
可以不单独声明委托
public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//当缺少类型时,自己去创建,记住这是为事件准备的委托,所以类型是EventArgs
这句可以不要
public delegate void OrderEventHandler(Customer customer, OrderEventArgs e)
public event OrderEventHandler Order;
改为
改为public EventHandler Order;
EventHandler 的定义
namespace System
{
//
// 摘要:
// 表示将用于处理不具有事件数据的事件的方法。
//
// 参数:
// sender:
// 事件源。
//
// e:
// 不包含事件数据的对象。
[ComVisible(true)]
public delegate void EventHandler(object sender, EventArgs e);
}
因此要把事件响应者类型进行修改
public class Waiter
{
internal void Action(Object sender, EventArgs e)
{
Customer customer = sender as Customer;//转换sender
OrderEventArgs orderInfor = e as OrderEventArgs;// 转换e
Console.WriteLine("I will serve you the dish-{0}", orderInfor.DishName);//e改为orderInfor
double price = 10;
switch (orderInfor.Size)//e改为orderInfor
{
case "small":
price = price * 05;
break;
case "large":
price = price * 1.5;
break;
default:
break;
}
customer.Bill +=price;
}
}
}
一个方法只做一件事
因此要对Think进行改造
public void Think()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Let me think...");
Thread.Sleep(1000);
}
this.OnOrder("m","large");
}
protected void OnOrder(string disName,string size)
{
if (this.Order != null)
{
OrderEventArgs e = new OrderEventArgs();
e.DishName = disName;
e.Size = size;
this.Order.Invoke(this, e);//事件的触发者用this代替了
}
}
完整代码
using System;
using System.Collections.Generic;
using System.Timers;
using System.Runtime.InteropServices;
using System.Collections;
using System.Linq;
using System.Windows.Forms;
using System.Threading;
namespace NamespaceEncasement
{
class Program
{
static void Main(string[] args)
{
Customer customer = new Customer();
Waiter waiter = new Waiter();
customer.Order += waiter.Action;//这个时候,Order已经变成了字段
customer.Action();
customer.PayTheBill();
}
}
public class OrderEventArgs : EventArgs
{
public string DishName { get; set; }
public string Size { get; set; }
}
//public delegate void OrderEventHandler(Customer customer, OrderEventArgs e);//当缺少类型时,自己去创建,记住这是为事件准备的委托,所以类型是EventArgs
public class Customer//事件拥有者
{
//用于存储或者引用事件处理器的
public double Bill { get; set; }
public EventHandler Order;
public void PayTheBill()
{
Console.WriteLine("I will pay ${0}", this.Bill);
}
//声明点菜事件
public void Walkin()
{
Console.WriteLine("Walk into the restaurant");
}
public void SitDown()
{
Console.WriteLine("Sit down.");
}
public void Think()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Let me think...");
Thread.Sleep(1000);
}
this.OnOrder("m","large");
}
protected void OnOrder(string disName,string size)
{
if (this.Order != null)
{
OrderEventArgs e = new OrderEventArgs();
e.DishName = disName;
e.Size = size;
this.Order.Invoke(this, e);//事件的触发者用this代替了
}
}
public void Action()
{
Console.ReadLine();
this.Walkin();
this.SitDown();
this.Think();
}
}
public class Waiter
{
internal void Action(Object sender, EventArgs e)
{
Customer customer = sender as Customer;//转换sender
OrderEventArgs orderInfor = e as OrderEventArgs;// 转换e
Console.WriteLine("I will serve you the dish-{0}", orderInfor.DishName);//e改为orderInfor
double price = 10;
switch (orderInfor.Size)//e改为orderInfor
{
case "small":
price = price * 05;
break;
case "large":
price = price * 1.5;
break;
default:
break;
}
customer.Bill +=price;
}
}
}