获取WPF控件的所有附加事件处理程序

laawzig2  于 2023-06-07  发布在  其他
关注(0)|答案(4)|浏览(200)

我正在开发一个应用程序,我为按钮动态分配事件。现在的事情是,我希望获得按钮单击事件的所有事件,因为我希望删除以前的处理程序。
我尝试将事件处理程序设置为null,如下所示:

Button.Click += null;

但是,我收到了一个运行时异常,无法分配null。
我希望知道已经附加到它的事件,以便我可以删除这些事件。
有人能帮我实现这一点吗?

ha5z0ras

ha5z0ras1#

您无法分配事件-只有附加(+=)和删除(-=)操作可用于客户端。
由于+=和-=是在声明事件的类型之外的事件上允许的唯一操作,因此外部代码可以添加和移除事件的处理程序,但不能以任何其他方式获取或修改事件处理程序的基础列表。

nkcskrwz

nkcskrwz2#

一个很好的模式是在某个地方声明一个Action removeAll,所以你可以这样做:

button.Click += handler
removeAll += () => button.Click -= handler

这样你就只需要跟踪一个变量,你可以通过调用removeAll()来清除所有的变量,而不是单独跟踪所有的处理程序,然后在每个处理程序上调用-=。如果您需要处理EventHandler的多个子类,这将特别方便,因为否则您必须使用多个列表来跟踪它们。

b1payxdu

b1payxdu3#

为了取得成果,这里有一个主要的黑客在其所有的荣耀。您可以修改它以获得事件的确切列表,等等。
用法:HasEventHandler(myCoolButton, "Click");

private static bool HasEventHandler(UIElement element, string eventName)
    {
        var events = element.GetType().GetEvents(Flags).Where(x => x.Name == eventName);

        foreach (var theEvent in events)
        {
            var fieldInfo = element.GetType().GetField($"{theEvent.Name}Event", Flags);
            RoutedEvent? eventKind = (RoutedEvent?) fieldInfo?.GetValue(element);
            if (eventKind is null)
                continue;

            // Look at the global event handlers store for any handlers.
            var store = typeof(UIElement)
                .GetField("EventHandlersStoreField", Flags)
                ?.GetValue(null); // `UncommonField<EventHandlersStore> EventHandlersStoreField`
            var method = store?.GetType().GetMethod("GetValue");
            var eventHandlersStore = method?.Invoke(store, new object[] { element });
            var getRoutedEventHandlers = eventHandlersStore?.GetType().GetMethod("GetRoutedEventHandlers");
            var handlers = (RoutedEventHandlerInfo[]?) getRoutedEventHandlers?.Invoke(eventHandlersStore, new[] { eventKind });

            if (handlers?.Any() == true)
                return true;
        }

        return false;
    }
xriantvc

xriantvc4#

你不能这样做(幸运的是)。想象一下,一些外部代码删除了 * 你的 * 事件处理程序,你的代码只是以静默的方式停止工作)。
(反射在这里不是一个选项,因为事件实现可能因类型而异)。通常,如果要以这种方式删除所有事件处理程序,则意味着存在设计错误。

相关问题