c# UWP 控件 Button (九)
(返回目录)
事件概述
⚫首先了解委托(delegate)
什么是委托?
委托是对方法的引用,是一个引用类型,所以它具有引用类型所具有的通性;
使用delegate关键字定义委托;相当于将方法引用赋值给一个变量,通过“变量+()”可以运行该方法;
这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性;
委托相当于函数指针;
委托指向的方法必须和委托具有相同的方法签名,即委托的参数数量、数据类型和顺序、返回值必须都要一致。
委托是对方法的引用,是一个引用类型,所以它具有引用类型所具有的通性;
使用delegate关键字定义委托;相当于将方法引用赋值给一个变量,通过“变量+()”可以运行该方法;
这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性;
委托相当于函数指针;
委托指向的方法必须和委托具有相同的方法签名,即委托的参数数量、数据类型和顺序、返回值必须都要一致。
委托的作用:
委托的优势在于他能引用多个方法;
委托可以让方法作为参数传递给其它方法;
委托的优势在于他能引用多个方法;
委托可以让方法作为参数传递给其它方法;
委托和事件
事件自身就是委托类型,由于委托可以绑定和调用多个方法,所以会为事件的处理带来方便。类只需要对外公开事件,就可以与外部的其它地方关联,从而实现事件订阅。
事件自身就是委托类型,由于委托可以绑定和调用多个方法,所以会为事件的处理带来方便。类只需要对外公开事件,就可以与外部的其它地方关联,从而实现事件订阅。
⚫事件(Event)
事件的前身是消息(Message);Window是消息驱动的操作系统,运行其上的程序也遵循这个机制运行。消息本质是一条数据,这条数据记载着消息的类别,消息的参数。面向对象的出现,微软把消息机制封装成事件模型。
在.net框架中,事件是将事件发送者(触发事件的对象)与事件接受者(处理事件的方法)相关联的一种代理类,即事件机制是通过代理类来实现的。当一个事件被触发时,由该事件的代理来通知(调用)处理该事件的相应方法。即事件基于委托,为委托提供了一种发布/订阅机制。
事件的三要素
事件发布者:具体到代码中也就是谁中定义了事件;
事件订阅者:可理解为“盯着”事件发布者的某个行为的对象;
事件处理方法:事件触发后要执行的方法。
事件订阅者:可理解为“盯着”事件发布者的某个行为的对象;
事件处理方法:事件触发后要执行的方法。
申明事件:
申明事件和申明字段相似,但由于事件随委托使用,所以事件的类型必须是委托,所以,先有委托申明。
//声明委托
public delegate void delegateTypeName();
//声明事件
public event delegateTypeName eventName;
public delegate void delegateTypeName();
//声明事件
public event delegateTypeName eventName;
例如Button类的公共事件Click:
在Button类的ButtonBase基类中某个地方进行了委托申明以及事件申明,代码如下:
public delegate void RoutedEventHandler(object sender,RoutedEventArgs e);
public event RoutedEventHandler Click;
订阅事件:
事件使用+=操作符进入就绪状态,即订阅事件。使用-=取消订阅。
在实例化的名为StartButton的按钮所在的项目中,项目目录下MainPage.g.cs文件中有隐藏代码如下,实现了click事件的订阅:
…………
this.startButton = (global::Windows.UI.Xaml.Controls.Button)(target);
((global::Windows.UI.Xaml.Controls.Button)this.startButton).Click += this.StartButton_Click;
((global::Windows.UI.Xaml.Controls.Button)this.startButton).Click += this.StartButton_Click;
…………
使用事件:
开发人员唯一要做的就是在MainPage.xaml.cs文件的StartButton_Click方法中写应用程序逻辑代码,在这反而不必理解委托,VS在后台全部做好啦。
private void StartButton_Click(object sender, RoutedEventArgs e)
{
//TODO…….
}
private void StartButton_Click(object sender, RoutedEventArgs e)
{
//TODO…….
}
事件的参数:
事件签名包含void返回类型和两个参数;
第一个参数:事件的来源sender,一个object,它引用引发事件的实例。即谁激发了这个事件处理程序,它可以获取到触发对象。例如:通过(sender as FrameworkElement).Name转换,将触发控件的名称拿出来。
第二个参数:EventArgs(或者EventArgs的派生类),它保存事件数据。 如果事件不生成事件数据,则第二个参数只是 EventArgs 的一个实例。 否则,第二个参数为从 EventArgs 派生的自定义类型,提供保存事件数据所需的全部字段或属性。
⚫路由事件(Routed Event)
事件系统在WPF中升级进化成为路由事件(Routed Event),并在其基础上衍生出命令传递机制(冒泡)。
路由事件是一种可以针对元素树中的多个侦听器而不是仅仅针对引发该事件的对象调用处理程序的事件,也就是说,触发事件源的父级或子级如果都有对该事件的监听,则都能触发事件。
路由事件与一般事件的区别在于:路由事件是一种用于元素树的事件,当路由事件触发后,它可以向上或向下遍历可视树和逻辑树,他用一种简单而持久的方式在每个元素上触发,而不需要任何定制的代码(如果用传统的方式实现一个操作,执行整个事件的调用则需要执行代码将事件串联起来)
路由事件的路由策略:
即路由事件实现遍历元素的方式,一般使用以下三种路由策略:
冒泡:由事件源向上传递一直到根元素。
直接:只有事件源才有机会响应事件。事件仅仅在源元素上触发,这个与普通的.Net事件的行为相同,不同的是这样的事件仍然会参与一些路由事件的特定机制,如事件触发器等;该事件唯一可能的处理程序是与其挂接的委托。
隧道:从元素树的根部调用事件处理程序并依次向下深入直到事件源。所有的隧道事件都以Preview开头。
即路由事件实现遍历元素的方式,一般使用以下三种路由策略:
冒泡:由事件源向上传递一直到根元素。
直接:只有事件源才有机会响应事件。事件仅仅在源元素上触发,这个与普通的.Net事件的行为相同,不同的是这样的事件仍然会参与一些路由事件的特定机制,如事件触发器等;该事件唯一可能的处理程序是与其挂接的委托。
隧道:从元素树的根部调用事件处理程序并依次向下深入直到事件源。所有的隧道事件都以Preview开头。
一般情况下,WPF提供的输入事件都是以隧道/冒泡对实现的。隧道事件常常被称为Preview事件
参考:
tiz198183 :WPF 路由事件
东南有大树 :WPF之路-路由事件