Как создать пользовательское перенаправленное событие (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
.
- Идентификатор перенаправленного события со стратегией восходящей маршрутизации событий называется
Определите методы доступа к событиям add и remove для среды CLR. Без методов доступа к событиям CLR вы сможете добавлять или удалять обработчики событий только с помощью прямых вызовов методов UIElement.AddHandler и UIElement.RemoveHandler. При использовании методов доступа к событиям CLR вы получаете следующие механизмы назначения обработчика событий:
- В языке XAML можно использовать синтаксис атрибутов для добавления обработчиков событий.
- В языке C# можно использовать операторы
+=
и-=
для добавления или удаления обработчиков событий. - В Visual Basic можно использовать инструкции AddHandler и RemoveHandler для добавления или удаления обработчиков событий.
Добавьте пользовательскую логику для активации перенаправленного события. Например, ваша логика может активировать событие на основе данных, введенных пользователем, и состояния приложения.
Пример
В следующем примере класс CustomButton
реализуется в пользовательской библиотеке элементов управления. Класс CustomButton
, который является производным от Button:
- Регистрирует RoutedEvent с именем
ConditionalClick
с помощью метода RegisterRoutedEvent и задает стратегию восходящей маршрутизации событий во время регистрации. - Назначает экземпляр
RoutedEvent
, возвращенный из вызова регистрации, в статическое поле только для чтения с именемConditionalClickEvent
. - Определяет методы доступа к событиям add и remove для среды 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
:
- В
CustomButton
вызывается перенаправленное событиеConditionalClick
. - Активируется обработчик событий
Handler_ConditionalClick
, подключенный кCustomButton
. - Перенаправленное событие
ConditionalClick
перемещается вверх по дереву элементов к контейнеруStackPanel1
. - Активируется обработчик событий
Handler_ConditionalClick
, подключенный кStackPanel1
. - Перенаправленное событие
ConditionalClick
продолжается перемещаться вверх по дереву элементов. Потенциально оно может активировать другие обработчики событийConditionalClick
, подключенные к другим пройденным элементам.
Обработчик событий Handler_ConditionalClick
получает следующие сведения о вызвавшее его событии:
- Объект sender, являющийся элементом, к которому подключен обработчик событий. Обработчик
sender
запускается дляCustomButton
первый раз, а дляStackPanel1
второй раз. - Объект RoutedEventArgs.Source, являющийся элементом, который изначально вызвал событие. В этом примере
Source
всегда являетсяCustomButton
.
Примечание.
Ключевое различие между перенаправленным событием и событием среды CLR заключается в том, что перенаправленное событие проходит по дереву элементов в поисках обработчиков, тогда как событие среды CLR не проходит по дереву элементов, а обработчики могут подключаться только к исходному объекту, вызвавшему событие. В результате перенаправленное событие sender
может быть любым пройденным элементом в дереве элементов.
Вы можете создать событие туннелирования так же, как и событие восходящей маршрутизации событий, за исключением того, что зададите стратегию маршрутизации в вызове регистрации события Tunnel. Дополнительные сведения о событиях туннелирования см. в разделе События ввода WPF.
См. также
.NET Desktop feedback