WPF附加事件与非附加事件

本文关键字:事件 WPF | 更新日期: 2023-09-27 17:58:12

问题是,经过我所有的研究,我仍然找不到常规路由事件和附加事件之间的区别。功能上的区别是什么?或者其他人同意没有?

实施

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事件字段,该字段具有调用base的自定义添加和删除访问器。AddHandler和base。RemoveHandler;这两者都是在ButtonBase派生的UIElement基类中声明的。相反,MouseDownEvent有两个静态方法AddMouseDownCHandler和RemoveMouseDownTHandler,它们最终调用UIElement中声明的相同的两个AddHandler和RemoveHandler方法,就像ClickEvent一样。

在静态类上声明的实际附加事件的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应用程序:

控件可以定义事件的处理程序控制权本身无法提升。这些偶发事件称为附加事件。例如,考虑Button控件在网格中。Button类定义Click事件,但Grid类不但是,您仍然可以定义网格中按钮的处理程序附加的Click事件XAML代码中的按钮控件。

在微软的学习资源中,"附加事件"一词似乎很模糊,尽管很明显,这里有两个不同但密切相关的概念:附加事件和XAML附加事件语法。我引用的两个微软消息源似乎都引用了XAML附加的事件语法,而不是实际的附加事件。但是,附带的事件概述MSDN页面确实向您展示了如何实现实际的附带事件,而培训工具包没有。

Mouse.MouseDownEvent是在具有相应静态添加和删除处理程序的静态类上声明的路由事件的示例,也称为附加事件。但是,ButtonBase.ClickEvent是一个普通的路由事件,尽管它仍然可以与XAML附加的事件语法一起使用,其方式与实际附加的事件相同。

实际附加事件的目的是允许开发人员为现有UIElement派生类声明新的路由事件,而不必对其进行子类化;这意味着你可以附加新的路由事件,而这些事件实际上不存在于你想要提升或处理它们的类中。但是,等一下。。。这难道不是纯路由事件的首要目的吗?

MSDN上的路由事件概述页面指出:http://msdn.microsoft.com/en-us/library/ms742806.aspx

功能定义:路由事件是一种可以调用的事件类型中多个侦听器上的处理程序元素树,而不仅仅是引发事件的对象。

从这个功能定义来看,任何路由事件本质上都提供了与附加事件完全相同的功能。因此,基本上,附加事件实际上只是在静态类上声明路由事件的一种方式,与普通路由事件相比并没有任何好处。

让我知道你的想法,因为我可能在这里错过了什么。

谢谢,Tim Valentine

WPF附加事件与非附加事件

差异主要是语法上的,两个委托引用都由WPF的EventManager处理,但所附事件为您提供了声明通用功能的能力,而无需膨胀所有类的实现。

在正常路由事件的情况下,类提供了一个接口,以便能够在某个时刻通过调用事件处理程序来响应事件。但WPF需要知道的是,它是否是从给定类型派生的对象,以及是否注册了处理程序。这意味着我们可以制作更简单的类层次结构,还支持开放-封闭原则(开放-扩展,封闭-修改)。通过这种方式,程序员可以定义几个类应该具有的新行为,但不需要修改原始类。

另请参阅附加属性

将注释复制到答案,这样它最终就不会丢失:

附加事件是可以附加到任何对象的事件,而不是仅定义事件的对象。

路由事件是一个事件可以路由到不是对象一部分的处理程序。

这是可能的事件既是路由事件又是附加事件。对于例如,Button.Click是一个附加事件,因为您可以附加事件发送到Button对象以外的对象。它也是一个路由事件因为它可以由中的多个Button.Click事件处理程序处理UI树,除非您停止此行为,例如标记事件如在其中一个处理程序中处理的。

(Rachel 12年11月8日20:39)