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;
}
4条答案
按热度按时间ha5z0ras1#
您无法分配事件-只有附加(+=)和删除(-=)操作可用于客户端。
由于+=和-=是在声明事件的类型之外的事件上允许的唯一操作,因此外部代码可以添加和移除事件的处理程序,但不能以任何其他方式获取或修改事件处理程序的基础列表。
nkcskrwz2#
一个很好的模式是在某个地方声明一个
Action removeAll
,所以你可以这样做:这样你就只需要跟踪一个变量,你可以通过调用
removeAll()
来清除所有的变量,而不是单独跟踪所有的处理程序,然后在每个处理程序上调用-=
。如果您需要处理EventHandler
的多个子类,这将特别方便,因为否则您必须使用多个列表来跟踪它们。b1payxdu3#
为了取得成果,这里有一个主要的黑客在其所有的荣耀。您可以修改它以获得事件的确切列表,等等。
用法:
HasEventHandler(myCoolButton, "Click");
xriantvc4#
你不能这样做(幸运的是)。想象一下,一些外部代码删除了 * 你的 * 事件处理程序,你的代码只是以静默的方式停止工作)。
(反射在这里不是一个选项,因为事件实现可能因类型而异)。通常,如果要以这种方式删除所有事件处理程序,则意味着存在设计错误。