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

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

我认为对该事件执行null检查即可:

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事件来挂接事件。可以只使用AddHandler方法直接传递您的路由事件,而这是某人必须做的事情才能将事件挂接到链上。最后,如果有人为该事件注册一个类处理程序,则不会使用CLR事件(在为MyButtonClass的任何实例引发该事件时都将得到通知)。如果查看类似UIElement.BuildRouteHelper的内容,您将看到WPF建立事件路由所经历的所有步骤以及引发事件时将调用的对象。

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

关于c# - 检查RoutedEvent是否具有任何处理程序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2716066/

10-11 02:44
查看更多