WPF附加事件与非附加事件

时间:2011-06-01 08:17:39

标签: c# wpf xaml routedevent

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

实施

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中注册,并以相同的方式存储为public,static,readonly字段。 ClickEvent有一个支持CLR事件字段,带有自定义添加和删除访问器,分别调用base.AddHandler和base.RemoveHandler;这两个都是在ButtonBase派生自的UIElement基类中声明的。 MouseDownEvent有两个静态方法AddMouseDownHandler和RemoveMouseDownHandler,它们最终调用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)定义了一个语言组件   和称为附加的事件类型   事件。附加的概念   event允许您为其添加处理程序   任意的特定事件   元素而不是元素   实际上定义或继承   事件。在这种情况下,既不是   对象可能引发事件   也不是目的地处理实例   定义或“拥有”该事件。

此外,适用于考试70-511的官方MCTS培训套件 - 使用Microsoft .NET Framework 4进行Windows应用程序开发:

  

控件可以定义   一个事件的处理程序   控制本身不能提高。这些   事件被称为附加事件。   例如,考虑Button控件   在网格中。 Button类定义了一个   单击事件,但Grid类可以   不。但是,您仍然可以定义一个   网格中按钮的处理程序   附加的Click事件   XAML代码中的按钮控件。

在整个Microsoft学习资源中,“附加事件”一词似乎模糊不清,尽管很明显这里有两个不同但非常密切相关的概念:附加事件和XAML附加事件语法。我引用的两个Microsoft源代码似乎都是指XAML附加事件语法,而不是实际附加事件。但是,附加的事件概述MSDN页面会继续向您展示如何实现实际的附加事件,而培训套件则不会这样做。

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

实际附加事件的目的是允许开发人员为现有的UIElement派生类声明新的路由事件,而不必对它们进行子类化;这意味着您可以添加新的路由事件,而不会将它们实际存在于您要引发或处理它们的类上。但是,等一下......首先,这不是一个纯路由事件的主要目的吗?

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

  

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

从该功能定义来看,似乎任何路由事件基本上都提供与附加事件相同的确切功能。所以基本上附加事件实际上只是在静态类上声明路由事件的一种方法,并没有真正提供优于正常路由事件的任何好处。

让我知道你认为,因为我可能在这里遗漏了一些东西。

谢谢, 蒂姆·瓦伦丁

2 个答案:

答案 0 :(得分:4)

区别主要是语法,两个委托引用都由WPF的EventManager处理,但附加事件给你的是能够声明泛型功能而不需要膨胀所有类的实现。

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

另见Attached Properties

答案 1 :(得分:1)

将评论复制到答案中,以免最终丢失:

<块引用>

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

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

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

(作者:Rachel 2012 年 11 月 8 日 20:39)