代码改变世界

Avalon学习笔记 之 路由事件

2005-07-12 23:09  Colin Han  阅读(2279)  评论(0编辑  收藏  举报
Avalon中又一个非常吸引人的功能——路由事件(Routed Event).
在某些概念上和附加属性有些类似。

概述

Avalon提供了一套事件路由技术,从而我们可以在父节点上接收和处理子节点的事件。
下图是路由事件的会意图。
RoutedEvent
微软定义了两种路由事件,分别称为深入(Tunneling)事件和冒出(Bubbling)(附:微软还定义了一种直接(Direct)事件,个人认为不能称之为路由事件)
对于深入事件,事件先由根节点进行处理,然后交由子节点处理,一级一级向下传,直到驱动这个事件的对象(如图Tunnel路径)。而冒出事件则正向反,现有驱动这个事件的对象处理,然后依次向上传递,直到根节点最后处理(相应的,直接事件只交由驱动这个事件的对象处理,不进行传递)。在整个处理路由的任何一个环节,都可以阻止这个事件的继续传递。

路由事件的事件参数必须从RoutedEventArgs继承,这个参数中包含一个属性Handled,事件处理函数可以通过将这个参数置为True而阻止路由事件的继续传递。

一个包含路由事件的对象的例子:
public class MyButtonSimple: Button
{
    
// Create a custom routed event by first registering a RoutedEvent
    
// This event uses the bubbling routing strategy
    public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent("Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));
    
// Provide CLR accessors for the event
    public event RoutedEventHandler Tap
    
{
        add 
{ AddHandler(TapEvent, value); } 
        remove 
{ RemoveHandler(TapEvent, value); }
    }


    
// This virtual method raises the Tap event
    protected virtual void OnTap()
    
{
        RoutedEventArgs newEvent 
= new RoutedEventArgs();
        newEvent.RoutedEvent 
= MyButtonSimple.TapEvent;
        RaiseEvent(newEvent);
    }


    
// For demonstration purposes we raise the event when the MyButtonSimple is clicked
    protected override void OnClick()
    
{
        OnTap();
    }

}

定义路由事件

必须使用EventManager.RegisterRoutedEvent注册一个路由事件
public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent("Tap"RoutingStrategy.Bubbletypeof(RoutedEventHandler), typeof(MyButtonSimple));
将它保存在一个只读静态成员中是为了将来更加容易的使用它。红色的部分声明这个路由事件的类型。例子中我们声明了一个冒出事件。

触发路由事件

为了使用它的路由功能,我们不能再使用传统的调用事件处理函数的逻辑,而必须使用下面的逻辑:
        RoutedEventArgs newEvent = new RoutedEventArgs();
        newEvent.RoutedEvent 
= MyButtonSimple.TapEvent;
        RaiseEvent(newEvent);

来驱动这个事件。

捕获事件

捕获路由事件分为两种情况,捕获本身的事件 和 捕获子节点的事件。
捕获本身的事件和传统的Windows应用一样的。下面是它们的语法:
C#:

MyButtonSimple button = new MyButtonSimple();
button.Tap 
+= new RoutedEventHandler(HandlerFunction);
XAML:
<MyButtonSimple Tap="HandlerFunction">button1</MyButtonSimple>

捕获子节点上的事件采用下面的语法:
C#:
ButtonContainer.AddHandler(MyButtonSimple.TapEvent, new RoutedEventHandler(HandlerFunction));
XAML:
<StackPanel Name="ButtonContainer"  Button.Click="HandlerFunction">