在上一节我们已经学了在控件(元素)中定义路由事件,而在非元素的类型中定义的路由事件,我们称为附加事件。所以,本质上讲,附加事件也是路由事件。
附加事件虽然定义在非元素的类型中,但却是在元素类型中引发,并且通过元素树进行传播。
附加事件其实与附加属性相似,但是不完全相同。定义附加事件时,分两个步骤,第一步是利用EventManager的RegisterRoutedEvent方法成员定义一个路由事件。
public static readonly RoutedEvent 路由事件名称 = EventManager.RegisterRoutedEvent(
name: "路由事件名称",
routingStrategy: 冒泡事件/隧道事件/直接事件,
handlerType: 路由事件委托的反射实例,
ownerType: 路由事件拥有者的反射实例;
第二步是将路由事件名称包装一下,它的包装有点特别。
public static void Add附加事件名称Handler(DependencyObject dependencyObject, RoutedEventHandler handler)
{
if (dependencyObject is UIElement uiElement)
{
uiElement.AddHandler(路由事件名称, handler);
}
}
public static void Remove附加事件名称Handler(DependencyObject dependencyObject, RoutedEventHandler handler)
{
if (dependencyObject is UIElement uiElement)
{
uiElement.RemoveHandler(路由事件名称, handler);
}
}
将路由事件名称包装成附回事件名称,需要定义两个静态方法成员,且成员命名规则必须如下定义:
Add<附加事件名称>Handler
Remove<附加事件名称>Handler
如此,WPF的事件系统便会通过内部反射机制知道开发者的意图。在添加和删除附加事件的定义中,第一个参数DependencyObject表示附加事件的宿主对象,第二个参数RoutedEventHandler表示一个委托,由外界传入,即当附加事件被触发时所执行的回调函数。
最后一点,谁附加了一个附加事件,谁就负责触发和编写触发后的回调函数代码逻辑。通常是某个控件去附加一个事件,因为控件的基类都是UIElement类,而只有UIElement才具有添加路由事件、删除路由事件、触发路由事件的功能。
- UIElement.AddHandler();添加一个路由事件;
- UIElement.RemoveHandler();删除一个路由事件;
- UIElement.RaiseEvent();触发一个路由事件;
在了解了这些关于附加事件的基础常识后,我们就可以用一个实际的例子来演示它的用法。下一节,附加事件的实战。
——重庆教主 2023年10月27日