检查RoutedEvent是否有任何处理程序

时间:2010-04-26 18:58:10

标签: c# event-handling wpf-controls click routed-events

我有一个自定义Button类,它在点击时总是执行相同的操作(打开一个特定的窗口)。我正在添加一个可以在按钮的XAML中分配的Click事件,就像常规按钮一样。

单击它时,我想执行Click事件处理程序(如果已分配),否则我想执行默认操作。问题是,显然没有办法检查是否有任何处理程序被添加到事件中。

我认为对事件的空检查会这样做:

if (Click == null) 
{ 
    DefaultClickAction(); 
} 
else 
{ 
    RaiseEvent(new RoutedEventArgs(ClickEvent, this));;
}

...但是不能编译。编译器告诉我,除了+ =或 - =之外,我不能对定义类之外的事件执行任何操作,虽然我正在尝试执行此操作检查INSIDE定义类。

我自己实现了正确的行为,但它很丑陋且冗长,我无法相信没有内置的方法来做到这一点。我一定错过了什么。

以下是相关代码:

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; }
    }

    //...
}

1 个答案:

答案 0 :(得分:2)

不,不可能。实际上,您所拥有的代码假定他们正在处理您控件本身的事件,但您宣布冒泡事件而不是直接事件,因此技术上可以听取事件的内容进一步提升元素链。此外,从技术上讲,不需要使用CLR事件来挂钩事件;一个人可以直接使用AddHandler方法传入你的路由事件,而这正是有人必须做的事情才能将事件挂钩到链上。最后,如果有人为事件注册了一个类处理程序(在为MyButtonClass的任何实例引发该事件时得到通知),则不会使用CLR事件。如果您查看类似UIElement.BuildRouteHelper的内容,您将看到WPF完成建立事件路由的所有步骤以及在引发事件时将调用的对象。

如果您确实需要知道是否有任何侦听器,那么最好创建一个仅CLR事件而不是路由事件。然后,您可以检查您的委托是否为非空。