Как создать пользовательское маршрутизируемое событие (WPF .NET)
Разработчики приложений и авторы компонентов Windows Presentation Foundation (WPF) могут создавать пользовательские маршрутизируемые события для расширения функциональности событий среды CLR. Сведения о возможностях перенаправленных событий см. в разделе Почему использовать перенаправленные события. В этой статье рассматриваются основы создания пользовательского маршрутизируемого события.
Необходимые условия
В статье предполагается, что у вас есть базовые знания о маршрутизированных событиях, а также что вы прочитали обзор маршрутизированных событий. Чтобы следовать примерам в этой статье, это поможет вам, если вы знакомы с языком разметки расширяемых приложений (XAML) и узнаете, как писать приложения Windows Presentation Foundation (WPF).
Этапы маршрутизированного события
Ниже приведены основные действия по созданию перенаправленного события:
Зарегистрируйте RoutedEvent, используя метод RegisterRoutedEvent.
Вызов регистрации возвращает экземпляр
RoutedEvent
, известный как идентификатор маршрутизированного события, который содержит имя зарегистрированного события, стратегию маршрутизации событий, и другие сведения о событии. Назначьте идентификатор статическому полю только для чтения. По соглашению:- Идентификатор перенаправленного события с стратегией называется
<event name>Event
. Например, если имя событияTap
, идентификатор должен быть названTapEvent
. - Идентификатор перенаправленного события с стратегией туннелирования называется
Preview<event name>Event
. Например, если имя событияTap
, идентификатор должен быть названPreviewTapEvent
.
- Идентификатор перенаправленного события с стратегией называется
Определите CLR , добавить и , удалить методы доступа к событиям. Без методов доступа к событиям CLR вы сможете добавлять или удалять обработчики событий только с помощью прямых вызовов методов UIElement.AddHandler и UIElement.RemoveHandler. С помощью аксессоров событий CLR вы получаете следующие механизмы назначения обработчика событий:
- Для языка разметки расширяемых приложений (XAML) можно использовать синтаксис атрибутов для добавления обработчиков событий.
- Для C# можно использовать операторы
+=
и-=
для добавления или удаления обработчиков событий. - Для VB можно использовать инструкции AddHandler и RemoveHandler для добавления или удаления обработчиков событий.
Добавьте пользовательскую логику для запуска маршрутизированного события. Например, ваша логика может активировать событие на основе пользовательского ввода и состояния приложения.
Пример
В следующем примере реализуется класс CustomButton
в пользовательской библиотеке элементов управления. Класс CustomButton
, производный от Button:
- Регистрирует RoutedEvent с именем
ConditionalClick
с помощью метода RegisterRoutedEvent и задает стратегию во время регистрации. - Назначает экземпляр
RoutedEvent
, возвращенный из вызова регистрации, статическому полю, доступному только для чтения, с именемConditionalClickEvent
. - Определяет среду CLR добавить и удалить методы доступа к событиям.
- Добавляет пользовательскую логику для вызова настраиваемого маршрутизируемого события при щелчке по
CustomButton
и применении внешнего условия. Хотя в примере кода возбуждается маршрутизируемое событиеConditionalClick
в переопределенном виртуальном методеOnClick
, вы можете вызвать событие любым выбранным вами способом.
public class CustomButton : Button
{
// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent ConditionalClickEvent = EventManager.RegisterRoutedEvent(
name: "ConditionalClick",
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(CustomButton));
// Provide CLR accessors for assigning an event handler.
public event RoutedEventHandler ConditionalClick
{
add { AddHandler(ConditionalClickEvent, value); }
remove { RemoveHandler(ConditionalClickEvent, value); }
}
void RaiseCustomRoutedEvent()
{
// Create a RoutedEventArgs instance.
RoutedEventArgs routedEventArgs = new(routedEvent: ConditionalClickEvent);
// Raise the event, which will bubble up through the element tree.
RaiseEvent(routedEventArgs);
}
// For demo purposes, we use the Click event as a trigger.
protected override void OnClick()
{
// Some condition combined with the Click event will trigger the ConditionalClick event.
if (DateTime.Now > new DateTime())
RaiseCustomRoutedEvent();
// Call the base class OnClick() method so Click event subscribers are notified.
base.OnClick();
}
}
Public Class CustomButton
Inherits Button
' Register a custom routed event with the Bubble routing strategy.
Public Shared ReadOnly ConditionalClickEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
name:="ConditionalClick",
routingStrategy:=RoutingStrategy.Bubble,
handlerType:=GetType(RoutedEventHandler),
ownerType:=GetType(CustomButton))
' Provide CLR accessors to support event handler assignment.
Public Custom Event ConditionalClick As RoutedEventHandler
AddHandler(value As RoutedEventHandler)
[AddHandler](ConditionalClickEvent, value)
End AddHandler
RemoveHandler(value As RoutedEventHandler)
[RemoveHandler](ConditionalClickEvent, value)
End RemoveHandler
RaiseEvent(sender As Object, e As RoutedEventArgs)
[RaiseEvent](e)
End RaiseEvent
End Event
Private Sub RaiseCustomRoutedEvent()
' Create a RoutedEventArgs instance.
Dim routedEventArgs As New RoutedEventArgs(routedEvent:=ConditionalClickEvent)
' Raise the event, which will bubble up through the element tree.
[RaiseEvent](routedEventArgs)
End Sub
' For demo purposes, we use the Click event as a trigger.
Protected Overrides Sub OnClick()
' Some condition combined with the Click event will trigger the ConditionalClick event.
If Date.Now > New DateTime() Then RaiseCustomRoutedEvent()
' Call the base class OnClick() method so Click event subscribers are notified.
MyBase.OnClick()
End Sub
End Class
В примере содержится отдельное приложение WPF, использующее разметку XAML для добавления экземпляра CustomButton
в StackPanel, а также назначение метода Handler_ConditionalClick
в качестве обработчика событий ConditionalClick
для элементов CustomButton
и StackPanel1
.
<Window x:Class="CodeSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:WpfControl;assembly=WpfControlLibrary"
Title="How to create a custom routed event" Height="100" Width="300">
<StackPanel Name="StackPanel1" custom:CustomButton.ConditionalClick="Handler_ConditionalClick">
<custom:CustomButton
Name="customButton"
ConditionalClick="Handler_ConditionalClick"
Content="Click to trigger a custom routed event"
Background="LightGray">
</custom:CustomButton>
</StackPanel>
</Window>
В коде программной части приложение WPF определяет метод обработчика событий Handler_ConditionalClick
. Методы обработчика событий можно реализовать только в коде программной части.
// The ConditionalClick event handler.
private void Handler_ConditionalClick(object sender, RoutedEventArgs e)
{
string senderName = ((FrameworkElement)sender).Name;
string sourceName = ((FrameworkElement)e.Source).Name;
Debug.WriteLine($"Routed event handler attached to {senderName}, " +
$"triggered by the ConditionalClick routed event raised on {sourceName}.");
}
// Debug output when CustomButton is clicked:
// Routed event handler attached to CustomButton,
// triggered by the ConditionalClick routed event raised on CustomButton.
// Routed event handler attached to StackPanel1,
// triggered by the ConditionalClick routed event raised on CustomButton.
' The ConditionalClick event handler.
Private Sub Handler_ConditionalClick(sender As Object, e As RoutedEventArgs)
Dim sourceName As String = CType(e.Source, FrameworkElement).Name
Dim senderName As String = CType(sender, FrameworkElement).Name
Debug.WriteLine($"Routed event handler attached to {senderName}, " +
$"triggered by the ConditionalClick routed event raised on {sourceName}.")
End Sub
' Debug output when CustomButton is clicked:
' Routed event handler attached to CustomButton,
' triggered by the ConditionalClick routed event raised on CustomButton.
' Routed event handler attached to StackPanel1,
' triggered by the ConditionalClick routed event raised on CustomButton.
Когда щёлкают по CustomButton
:
- Событие маршрутизации
ConditionalClick
вызывается наCustomButton
. - Запускается обработчик событий
Handler_ConditionalClick
, подключенный кCustomButton
. -
ConditionalClick
маршрутизируемое событие проходит по дереву элементов доStackPanel1
. - Запускается обработчик событий
Handler_ConditionalClick
, подключенный кStackPanel1
. - Маршрутизируемое событие
ConditionalClick
поднимается вверх по дереву элементов, потенциально активируя другие обработчики событийConditionalClick
, прикрепленные к другим проходящим элементам.
Обработчик событий Handler_ConditionalClick
получает следующие сведения о событии, вызвавшее его:
- Объект отправителя, который является элементом, к которому подключен обработчик событий.
sender
будетCustomButton
при первом запуске обработчика иStackPanel1
второй раз. - Объект RoutedEventArgs.Source, который является элементом, который первоначально вызвал событие. В этом примере
Source
всегдаCustomButton
.
Заметка
Ключевое различие между маршрутизированным событием и событием CLR заключается в том, что маршрутизированное событие проходит по дереву элементов, ища обработчики, тогда как событие CLR не проходит по дереву элементов, и обработчики могут подключаться только к исходному объекту, вызвавшему событие. В результате маршрутизируемое событие sender
может быть любым элементом в дереве элементов.
Событие туннелирования можно создать так же, как и событие бублинга, за исключением того, что вы задали стратегию маршрутизации в вызове регистрации событий на Tunnel. Дополнительные сведения о событиях туннелирования см. в разделе о событиях ввода WPF.
См. также
- Обзор
маршрутизированных событий - Обзор входных данных
- Обзор разработки элементов управления
- Обработать маршрутизированное событие.
.NET Desktop feedback