【问题标题】:WPF Custom Routed Events - How to UnSubscribe?WPF 自定义路由事件 - 如何取消订阅?
【发布时间】:2025-12-08 22:45:02
【问题描述】:

如何从一个自定义路由事件中取消注册。

我有以下代码(自定义路由事件非常标准)

//Dispatch the Video Detection Movements
public delegate void MovementRoutedEventHandler( object sender
                                                , MovementRoutedEventArgs e);
public class MovementRoutedEventArgs : RoutedEventArgs
{
    private readonly DahuaDevice _device;
    private readonly byte[] _canals;
    private readonly DateTime _when;

    public MovementRoutedEventArgs(DahuaDevice device, byte[] canals, DateTime when)
    {
        _device = device;
        _canals = canals;
        _when = when;
    }
    public DahuaDevice Device
    {
        get { return _device; }
    }
    public Byte[] Canals
    {
        get { return _canals; }
    }
    public DateTime When
    {
        get { return _when; }
    }
}
public static RoutedEvent MovementEvent = EventManager.RegisterRoutedEvent(
        "Movement"
    , RoutingStrategy.Tunnel
    , typeof(MovementRoutedEventHandler)
    , typeof(Window)
);

public event RoutedEventHandler Movement
{
    add { AddHandler(MovementEvent, value); }
    remove { RemoveHandler(MovementEvent, value); }
}
public void RaiseMovementEvent(DahuaDevice device, byte[] canals, DateTime when)
{
    RaiseEvent(new MovementRoutedEventArgs(device, canals, when)
    {
        RoutedEvent = MovementEvent
    });
}

现在一个类将使用这一行订阅此事件:

//Receive the Movement events
EventManager.RegisterClassHandler( 
      typeof(Window)
    , Main.MovementEvent
    , new Main.MovementRoutedEventHandler(MovementHandler));

当我关闭类实例时,我应该取消订阅事件(否则,实例不会被垃圾回收)。

我应该怎么称呼?我试过RegisterClassHandler(typeof(Window), Main.MovementEvent, **null**),但我得到了一个例外......

欢迎任何帮助。提前致谢。

JM

【问题讨论】:

    标签: wpf events routed


    【解决方案1】:

    您可以使用 System.Windows.Window 类(通常来自 UIElement 类)的RemoveHandler 方法。

    代码可能如下所示:

    Main.RemoveHandler( Main.MovementEvent
                      , new Main.MovementRoutedEventHandler(MovementHandler));
    

    【讨论】:

    • 非常感谢您的快速回答。
    • 很高兴能帮到你。
    【解决方案2】:

    我不确定我是否完全理解你在做什么,但我会投入两分钱。

    您的 EventManager.RegisterClassHandler 调用应放置在您希望注册的类的静态构造函数中。这将适用于该类的所有实例,并且不应影响垃圾收集。

    如果您希望在每个实例级别上注册/取消注册事件,请使用传统的

    myEvent += myDelegate;
    myEvent -= myDelegate;
    

    希望这会有所帮助。

    【讨论】:

    • 感谢您的回答,但是当它们是“自定义路由事件”时,您可以直接使用 + 和 - ...我不确定。我会将 RegisterClassHandler 放在静态构造函数中以避免内存泄漏。
    • 是的,您可以将 + 和 - 用于自定义路由事件。这些用于实例级别,但是由于您的解决方案似乎希望类的所有实例都订阅事件,因此 EventManager.RegisterClassHandler 是要走的路。然而,同样重要的是要注意注册到事件的方法应该是静态的,否则你会遇到你关心的内存泄漏问题。看到这个link