Подтвердить что ты не робот

Присоединенные события WPF против несанкционированных событий

Вопрос в том, что после всех моих исследований я все еще не могу найти разницу между регулярным маршрутизируемым событием и присоединенным событием. Какова функциональная разница? или другие согласны с тем, что их нет?

Реализация

Класс ButtonBase объявляет маршрутизируемое событие с именем ClickEvent; нормальное маршрутизируемое событие.

public static readonly RoutedEvent ClickEvent = EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ButtonBase));

[Category("Behavior")]
public event RoutedEventHandler Click
{
    add
    {
        base.AddHandler(ClickEvent, value);
    }
    remove
    {
        base.RemoveHandler(ClickEvent, value);
    }
}

Класс Mouse объявляет маршрутизируемое событие с именем MouseDownEvent; присоединенное событие.

public static readonly RoutedEvent MouseDownEvent = EventManager.RegisterRoutedEvent("MouseDown", RoutingStrategy.Bubble, typeof(MouseButtonEventHandler), typeof(Mouse));

public static void AddMouseDownHandler(DependencyObject element, MouseButtonEventHandler handler)
{
    UIElement.AddHandler(element, MouseDownEvent, handler);
}

public static void RemoveMouseDownHandler(DependencyObject element, MouseButtonEventHandler handler)
{
    UIElement.RemoveHandler(element, MouseDownEvent, handler);
}

Оба события регистрируются в EventManager и сохраняются как общедоступные, статические, только для чтения поля таким же образом. В ClickEvent есть поле событий CLR для поддержки с пользовательскими добавлениями и удалениями, которые вызывают base.AddHandler и base.RemoveHandler соответственно; оба из которых объявлены в базовом классе UIElement, из которого берет ButtonBase. MouseDownEvent вместо этого имеет два статических метода AddMouseDownHandler и RemoveMouseDownHandler, которые в конечном итоге вызывают те же два метода AddHandler и RemoveHandler, объявленные в UIElement, как и ClickEvent.

Статические методы Add * Handler и Remove * Handler для действительных прикрепленных событий, объявленных в статическом классе, должны соответствовать определенному соглашению об именах, чтобы позволить системе событий WPF использовать отражение, чтобы найти соответствующие добавления и удаления обработчиков во время выполнения.

<ч/" >

Использование

Оба события могут иметь обработчики, прикрепленные в XAML, следующим образом:

<Grid Button.Click="Grid_Click"
      Mouse.MouseDown="Grid_MouseDown">
</Grid>

Оба события могут быть прикреплены в коде следующим образом:

// Attach ClickEvent handler.
myGrid.AddHandler(Button.ClickEvent, new RoutedEventHandler(Grid_Click));

// Attach MouseDownEvent handler.
Mouse.AddMouseDownHandler(myGrid, Grid_MouseDown);

Как вы можете видеть, оба события могут быть привязаны к элементам, которые не владеют или не объявляют их.

<ч/" >

Заключение - Что такое прикрепленное событие?

Документация MSDN гласит: http://msdn.microsoft.com/en-us/library/bb613550.aspx

Расширяемый язык разметки приложений (XAML) определяет языковой компонент и тип события, называемого присоединенным мероприятие. Концепция присоединенного событие позволяет добавить обработчик для конкретное событие произвольному а не элементу, который фактически определяет или наследует мероприятие. В этом случае ни объект, потенциально поднимающий событие или экземпляр обработки назначения определяет или иным образом "владеет" событием.

Кроме того, официальный учебный комплект MCTS для экзамена 70-511 - разработка приложений Windows с Microsoft.NET Framework 4 гласит:

Можно определить элемент управления обработчик события, который контроль сам не может поднять. Эти инциденты называются приложенными событиями. Например, рассмотрите элементы управления Button в сетке. Класс Button определяет Событие Click, но класс Grid не. Однако вы все же можете определить обработчик для кнопок в сетке прикрепление события Click Управление кнопками в коде XAML.

Термин "присоединенное событие", по-видимому, размывается во всех учебных ресурсах Microsoft, хотя ясно, что здесь есть две разные, но очень тесно связанные концепции: приложенные события и синтаксис синтаксиса XAML. Оба источника Microsoft, о которых я цитировал, похоже, относятся к синтаксису синтаксиса XAML, а не к фактическим присоединенным событиям. Тем не менее, страница с подробными сведениями о подключенных событиях продолжает показывать, как реализовать фактическое присоединенное событие, в котором нет учебного комплекта.

Mouse.MouseDownEvent - пример маршрутизируемого события, объявленного в статическом классе, с соответствующими статическими обработчиками добавления и удаления, иначе известными как присоединенное событие. Тем не менее, ButtonBase.ClickEvent является обычным маршрутизируемым событием, хотя он все равно может использоваться с синтаксисом событий XAML в том же порядке, что и фактическое присоединенное событие.

Цель фактического присоединенного события состоит в том, что он позволяет разработчикам объявлять новые маршрутизируемые события для существующих классов, основанных на UIElement, без необходимости их подкласса; что означает, что вы можете просто присоединить новые маршрутизируемые события без их фактического существования на классах, которые вы хотите повысить или обработать. Но, подождите минутку... разве это не главная цель чистого маршрутизируемого события?

Страница обзора маршрутизируемых событий в MSDN: http://msdn.microsoft.com/en-us/library/ms742806.aspx

Функциональное определение: маршрутизируемое событие это тип события, которое может вызывать обработчиков на нескольких слушателях в дерева элементов, а не только на объект, который поднял событие.

Из этого функционального определения кажется, что любое маршрутизируемое событие по существу обеспечивает ту же самую точную функциональность, что и присоединенное событие. Таким образом, в основном присоединенное событие на самом деле является просто средством объявления маршрутизируемого события в статическом классе и на самом деле не дает никакой выгоды по сравнению с обычными маршрутизируемыми событиями.

Сообщите мне, что вы думаете, потому что я могу что-то пропустить здесь.

Спасибо, Тим Валентайн

4b9b3361

Ответ 1

Разница в основном синтаксическая, обе ссылки на делегаты обрабатываются WPF EventManager, но то, что вложенные события дают вам, - это способность объявлять общие функции без необходимости раздувать реализацию всех ваших классов.

В случае нормального маршрутизируемого события класс предоставляет интерфейсу возможность в какой-то момент реагировать на событие, вызывая обработчик события. Но все WPF нужно знать, если это объект, полученный из определенного типа, и если обработчик был зарегистрирован. Это означает, что мы можем упростить иерархии классов, а также поддерживать принцип открытого закрытия (Open to Extension, Closed to Modification). Таким образом, программист может определить новое поведение, которое должно иметь несколько классов, но не нужно изменять исходные классы.

См. также Приложенные свойства