【问题标题】:Checking if a RoutedEvent has any handlers检查 RoutedEvent 是否有任何处理程序
【发布时间】:2010-04-26 18:58:09
【问题描述】:

我有一个自定义 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; }
    }

    //...
}

【问题讨论】:

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


    【解决方案1】:

    不,这是不可能的。实际上,您拥有的代码假定他们正在处理您的控件本身的事件,但您声明的是 Bubble 事件而不是 Direct 事件,因此从技术上讲,有些东西可以监听该事件更进一步的元素链。此外,从技术上讲,不需要使用 CLR 事件来挂钩事件;可以只使用 AddHandler 方法直接传递您的路由事件,这就是人们必须做的事情才能将事件进一步挂钩链。最后,如果有人为事件注册了一个类处理程序,则不会使用 CLR 事件(每当为 MyButtonClass 的任何实例引发该事件时都会收到通知)。如果您查看 UIElement.BuildRouteHelper 之类的内容,您将看到 WPF 建立事件路由所经过的所有步骤以及在引发事件时将调用的对象。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      • 1970-01-01
      • 1970-01-01
      • 2012-12-13
      • 2013-03-05
      • 1970-01-01
      相关资源
      最近更新 更多