我有一个自定义的 Button 类,它在被点击时总是执行相同的操作(打开特定窗口)。我正在添加一个可以在按钮的 XAML 中分配的 Click 事件,就像常规按钮一样。
当它被点击时,如果已经分配了一个,我想执行 Click 事件处理程序,否则我想执行默认操作。问题是显然没有办法检查是否有任何处理程序已添加到事件中。
我认为对事件进行空检查就可以了:
if (Click == null)
{
DefaultClickAction();
}
else
{
RaiseEvent(new RoutedEventArgs(ClickEvent, this));;
}
...但这无法编译。编译器告诉我,除了 += 或 -= 之外,我不能对定义类之外的事件执行任何操作,尽管我正在尝试在定义类内部执行此检查。
我自己实现了正确的行为,但它既丑陋又冗长,我不敢相信没有内置的方法可以做到这一点。我一定是遗漏了什么。
相关代码如下:
public class MyButtonClass : Control
{
//...
public static readonly RoutedEvent ClickEvent =
EventManager.RegisterRoutedEvent("Click",
RoutingStrategy.Bubble,
typeof(RoutedEventHandler),
typeof(MyButtonClass));
public event RoutedEventHandler Click
{
add { ClickHandlerCount++; AddHandler(ClickEvent, value); }
remove { ClickHandlerCount--; RemoveHandler(ClickEvent, value); }
}
private int ClickHandlerCount = 0;
private Boolean ClickHandlerExists
{
get { return ClickHandlerCount > 0; }
}
//...
}
最佳答案
不,这是不可能的。实际上,您拥有的代码假定他们正在处理您控件本身的事件,但您声明的是 Bubble 事件而不是 Direct 事件,因此从技术上讲,某些东西可以监听该事件进一步向上元素链。此外,从技术上讲,不需要使用 CLR 事件来 Hook 事件;可以只使用 AddHandler 方法直接传递您的路由事件,这就是有人必须做的事情才能将事件进一步挂接到链上。最后,如果有人为该事件注册了一个类处理程序,则不会使用 CLR 事件(每当为您的 MyButtonClass 的任何实例引发该事件时都会收到通知)。如果您查看 UIElement.BuildRouteHelper 之类的内容,您将看到 WPF 为建立事件路由以及在引发事件时将调用的对象而经历的所有步骤。
如果您真的需要知道是否有任何监听器,那么您最好创建一个仅 CLR 事件而不是路由事件。然后您可以检查您的委托(delegate)是否为非空。
关于c# - 检查 RoutedEvent 是否有任何处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2716066/