深入浅出WPF-08.Event( 事件)01

事件(Event)

首先我们来继续说一下UI组件树,因为WPF事件 的路由环境就是组件树。WPF中的树有两种,一种是逻辑树(Logical Tree),一种是可视元素树(Visual Tree)。逻辑树的显著特点就是它完全由布局组件和控件构成,每个结点不是布局控件就是组件。我们把WPF的控件解剖后继续观察,WPF控件本身是由一颗更细微级别的组件组成的树。这些可视化的组件都是派生自Visual类的。WPF的路由事件是沿着可视元素树进行传递的,只有这样,藏在模板里的控件才能够把消息传递出来。前面我们说过,当这棵树上的某个节点激发了某个事件时,可以通过程序选择通过传统的直接事件模式响应这个事件,也可以让这个事件在UI树中沿着一定的方向传递下去,这个过程就是路由的过程。

事件的前身是消息。Windows是消息驱动的操作系统,消息的本质就是一条数据。事件是基于消息的封装。事件的3个关键点:

1)事件拥有者:即消息的发送者。事件的宿主可以在某些条件下激发她拥有的事件,即事件被触发。事件被触发了则消息被发送。

2)事件的响应者:即消息的接收者、处理者、事件接收者使用事件处理器(Event Handler)对事件作出响应。

3)事件的订阅关系:事件的拥有者可以随时激发事件,但事件激发后会不会得到响应要看有没有事件的响应者,或者说要看这个事件是否被关注了。如果对象A关注对象B 的某个事件是否发生,则称A订阅了B的事件。事件实际上是一个使用evnet关键字修饰的委托类型的成员变量,事件处理器则是一个函数。说A订阅了B的事件,本质上就是让B.Event与A.EventHandle关联起来。所谓的事件激发就是B.Evnet被调用,这时,与其关联的A.EvnetHandle就会被调用。

在上面的事件模型中,事件的响应者通过订阅关系直接关联在事件拥有者的事件上,为了与WPF的路由事件模型区分开,我们把这种事件模型成为直接事件模型或者CLR事件模型。因为CLR事件本质上是一个拥有event关键字修饰的委托实例。

在CLR直接事件模型中,事件的拥有者就是消息的发送者sender。实际上,只要支持事件的委托与响应事件的方法在签名上保持一致(即参数列表和返回值一致),则一个事件可以由多个事件处理器响应(多播事件)、一个事件处理器也可以响应多个事件。

不完美之处:事件的响应者和事件的拥有者之间必须建立订阅这个联系。每对消息是 发送-->响应 的关系,必须建立显示的点对点的订阅关系。事件的宿主必须能够直接访问事件的响应者,不然无法直接建立关系。为了解决这个问题,降低事件订阅带来的耦合度和代码量,WPF退出了路由事件机制。

路由事件和直接事件的区别在于,直接事件激发时,发送者直接将消息通过订阅交给事件响应者,事件响应者使用其事件处理器方法对事件的发生作出相应;路由事件的事件拥有者和事件响应者之间没有直接显示的订阅关系,事件的拥有者只负责激发事件,事件将由谁来响应她并不知道。事件响应者安装了事件的侦听器,针对某类事件进行侦听,当有此类事件传递到,此时事件响应者就使用事件处理器来响应事件并决定事件是否继续传递。

posted @ 2020-07-27 15:31  蜗牛的希望  阅读(304)  评论(0编辑  收藏  举报