Проверка, есть ли у RoutedEvent какие-либо обработчики - PullRequest
3 голосов
/ 26 апреля 2010

У меня есть собственный класс Button, который всегда выполняет одно и то же действие при нажатии (открытие определенного окна). Я добавляю событие Click, которое может быть назначено в XAML кнопки, как обычная кнопка.

Когда его щелкают, я хочу выполнить обработчик события 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; }
    }

    //...
}

1 Ответ

2 голосов
/ 18 октября 2011

Нет, это невозможно. На самом деле ваш код предполагает, что они обрабатывают событие на вашем элементе управления, но вы объявляете событие Bubble , а не событие Direct , так что технически что-то может прослушивать событие далее цепочка элементов. Кроме того, технически не нужно использовать событие CLR, чтобы перехватить событие; можно просто использовать метод AddHandler, напрямую передавая ваше перенаправленное событие, и это то, что кто-то должен был бы сделать, чтобы связать событие дальше по цепочке. Наконец, событие CLR не будет использоваться, если кто-то зарегистрирует обработчик класса для этого события (чтобы получать уведомление всякий раз, когда это событие вызывается для любого экземпляра вашего MyButtonClass). Если вы посмотрите на что-то вроде UIElement.BuildRouteHelper, вы увидите все шаги, которые проходит WPF для установления маршрута события, и объекты, которые будут вызываться при возникновении события.

Если вам действительно нужно знать, есть ли какие-либо слушатели, вам лучше создать событие только для CLR, а не перенаправленное событие. Затем вы можете проверить, не является ли ваш делегат ненулевым.

...