实现
ButtonBase类声明了一个名为ClickEvent的路由事件,这是一个普通的路由事件。
public static readonly RoutedEvent ClickEvent = EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ButtonBase));
[Category("Behavior")]
public event RoutedEventHandler Click
{
add
{
base.AddHandler(ClickEvent, value);
}
remove
{
base.RemoveHandler(ClickEvent, value);
}
}
Mouse类声明了一个名为MouseDownEvent的路由事件;这是一个附加事件。
public static readonly RoutedEvent MouseDownEvent = EventManager.RegisterRoutedEvent("MouseDown", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(Mouse));
public static void AddMouseDownHandler(DependencyObject element, MouseButtonEventHandler handler)
{
UIElement.AddHandler(element, MouseDownEvent, handler);
}
public static void RemoveMouseDownHandler(DependencyObject element, MouseButtonEventHandler handler)
{
UIElement.RemoveHandler(element, MouseDownEvent, handler);
}
两个事件都在EventManager中注册,并以相同的方式作为公共、静态和只读字段存储。ClickEvent具有支持CLR事件字段,其自定义add和remove访问器调用base.AddHandler和base.RemoveHandler,这两个访问器在ButtonBase派生类继承的UIElement基类中声明。而MouseDownEvent则具有两个静态方法AddMouseDownHandler和RemoveMouseDownHandler,最终调用与ClickEvent相同的两个在UIElement中声明的AddHandler和RemoveHandler方法。
在静态类上声明的实际附加事件的Add*Handler和Remove*Handler静态方法必须遵循特定的命名约定,以便WPF事件系统使用反射在运行时找到适当的添加和删除处理程序。
用法
在XAML中,这两个事件都可以按照以下方式附加处理程序:
<Grid Button.Click="Grid_Click"
Mouse.MouseDown="Grid_MouseDown">
</Grid>
以下是如何在代码中附加这两个事件:
// Attach ClickEvent handler.
myGrid.AddHandler(Button.ClickEvent, new RoutedEventHandler(Grid_Click));
// Attach MouseDownEvent handler.
Mouse.AddMouseDownHandler(myGrid, Grid_MouseDown);
正如您所看到的,这两个事件都可以附加到不拥有或声明它们的元素上。
结论 - 什么是附加事件?
MSDN文档说明: http://msdn.microsoft.com/en-us/library/bb613550.aspx
可扩展应用程序标记语言(XAML)定义了一种称为附加事件的语言组件和事件类型。附加事件的概念使您能够将特定事件的处理程序添加到任意元素,而不是添加到实际定义或继承事件的元素。在这种情况下,潜在引发事件的对象和目标处理实例都不定义或以其他方式“拥有”该事件。
此外,官方的MCTS培训套件70-511考试 - 使用Microsoft .NET Framework 4开发Windows应用程序也指出:
“附加事件”这个术语在微软的学习资源中似乎有些模糊,尽管很明显这里涉及到两个不同但非常密切相关的概念:附加事件和XAML附加事件语法。我引用的两个微软资源似乎都指的是XAML附加事件语法,而不是实际的附加事件。然而,MSDN页面上的“附加事件概述”确实会告诉你如何实现一个实际的附加事件,而培训套件则不会。一个控件可以定义对其自身无法引发的事件的处理程序。这些事件称为附加事件。例如,在网格中的按钮控件。Button类定义了Click事件,但Grid类没有。但是,您仍然可以通过在XAML代码中附加Button控件的Click事件来定义网格中的按钮的处理程序。
Mouse.MouseDownEvent是一个静态类声明的路由事件示例,具有相应的静态add和remove处理程序,也称为附加事件。然而,ButtonBase.ClickEvent是一个普通的路由事件,虽然它仍然可以像实际的附加事件一样使用XAML附加事件语法。
实际附加事件的目的是允许开发人员为现有的UIElement派生类声明新的路由事件,而无需对它们进行子类化;这意味着您可以只附加新的路由事件,而不必将它们实际存在于您想要在其上引发或处理它们的类中。但是,等一下...这不是纯路由事件的主要目的吗?
MSDN上的路由事件概述页面说明:http://msdn.microsoft.com/en-us/library/ms742806.aspx 功能定义:路由事件是一种事件类型,可以在元素树中的多个侦听器上调用处理程序,而不仅仅是在引发事件的对象上。
从这个功能定义来看,任何路由事件本质上都提供与附加事件完全相同的功能。因此,基本上,附加事件只是在静态类上声明路由事件的一种手段,并没有比普通路由事件更多的好处。
请告诉我您的想法,因为我可能会漏掉某些东西。
谢谢, Tim Valentine