从控件-WPF中注销类处理程序

本文关键字:处理 程序 注销 控件 -WPF | 更新日期: 2023-09-27 17:59:13

我已经通过WPF中的文本框注册了GotFocusEvent的事件处理程序。

EventManager.RegisterClassHandler(typeof(TextBox), TextBox.GotFocusEvent, new RoutedEventHandler(TextBox_GotFocus));

现在,有没有办法从文本框中删除已注册的处理程序?

更新:我检查了以下链接

WPF自定义路由事件-如何取消订阅?

然而,这对我没有帮助,因为提到的控件是自定义控件,在我的情况下,它是默认的TextBox控件。

在我的情况下,我找不到RemoveHandler。有什么建议吗?

从控件-WPF中注销类处理程序

正如您的问题评论中所述,类处理程序不能注销。我的建议如下:在处理程序的开头添加一个if语句,检查实际的方法体是否应该执行。这可能看起来如下:

private void MyTextBoxClassHandler (object sender, RoutedEventArgs e)
{
    if (CheckIfHandlerShouldExecute() == false)
        return;
    // The actual code that should be executed in the handler resides here.
}

这并不能防止调用处理程序,但如果不满足某个条件,则不会执行您的逻辑。

没有办法注销类处理程序,但您可以在静态类中管理事件,在该类中注册一次类处理程序并根据需要添加/删除实例处理程序。你可以暴露正常的EventHandlers,也可以使用反应扩展来实现这一点:

public static class GlobalEvents
{
    static readonly ClassHandlerSubject s_TextBoxGotFocus = new ClassHandlerSubject(typeof(TextBox), UIElement.GotFocusEvent);
    public static IObservable<RoutedEventArgs> TextBoxGotFocus => s_TextBoxGotFocus.Events;
    class ClassHandlerSubject
    {
        readonly Lazy<Subject<RoutedEventArgs>> m_Subject;
        public IObservable<RoutedEventArgs> Events => m_Subject.Value;
        public ClassHandlerSubject(Type classType, RoutedEvent routedEvent) =>
            m_Subject = new Lazy<Subject<RoutedEventArgs>>(() =>
            {
                EventManager.RegisterClassHandler(classType, routedEvent, new RoutedEventHandler(OnEventReceived));
                return new Subject<RoutedEventArgs>();
            });
        private void OnEventReceived(object sender, RoutedEventArgs e) => m_Subject.Value.OnNext(e);
    }
}

这样使用:

//subscribe
var subscription = GlobalEvents.TextBoxGotFocus.Subscribe(TextBox_GotFocus);
//... receive events
//remove my subscription
subscription.Dispose();

如果您一次只有一个类的实例,那么您希望订阅该事件。与@Alex类似,我在类中调用了一个静态事件。在构造函数中,我获取一个实例引用,然后用于我的事件。

public partical class MyWindow : Window
{
    public static MyWindow Current { get; private set; }
    public MyWindow() : base()
    {
        InitializeComponent();
        Current = this;
    }
    static MyWindow()
    {
        EventManager.RegisterClassHandler(typeof(MyWindow),
                System.Windows.Input.Keyboard.KeyUpEvent,
                new System.Windows.Input.KeyEventHandler(AllKeyUp_static), true);
    }
    private static void AllKeyUp_static(object sender, System.Windows.Input.KeyEventArgs e)
    {
        Current?.AllKeyUp_instance(sender, e);
    }
    private void AllKeyUp_instance(object sender, System.Windows.Input.KeyEventArgs e)
    {
         // HANDLE EVENT
    }
}

这将做两件事。首先,它可以防止先前的类实例因垃圾处理而变得不可收集。第二个-自动分配当前实例以利用事件。