Маршрутизируемое событие — это тип события, которое может вызывать обработчики для нескольких слушателей в дереве элементов, а не только для объекта, вызвавшего событие. Это в основном событие CLR, которое поддерживается экземпляром класса Routed Event. Он зарегистрирован в системе событий WPF. RoutedEvents имеют три основные стратегии маршрутизации, которые заключаются в следующем —
- Прямое событие
- Бублинг событие
- Туннельное Событие
Прямое событие
Прямое событие аналогично событиям в формах Windows, которые создаются элементом, в котором происходит событие.
В отличие от стандартного события CLR, события с прямой маршрутизацией поддерживают обработку классов, и их можно использовать в установщиках событий и триггерах событий в вашем стиле пользовательского элемента управления.
Хорошим примером прямого события будет событие MouseEnter.
Бублинг событие
Событие барботирования начинается с элемента, из которого происходит событие. Затем он перемещается вверх по визуальному дереву к верхнему элементу визуального дерева. Итак, в WPF самый верхний элемент — это, скорее всего, окно.
Туннельное Событие
Вызываются обработчики событий в корне дерева элементов, и затем событие перемещается по визуальному дереву ко всем дочерним узлам, пока не достигнет элемента, в котором возникло событие.
Разница между пузырьковым и туннельным событиями заключается в том, что туннельное событие всегда начинается с предварительного просмотра.
В приложении WPF события часто реализуются в виде пары туннелирование / пузыри. Итак, у вас будет предварительный просмотр MouseDown, а затем событие MouseDown.
Ниже приведен простой пример маршрутизируемого события, в котором кнопка и три текстовых блока создаются с некоторыми свойствами и событиями.
<Window x:Class = "WPFRoutedEvents.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" Title = "MainWindow" Height = "450" Width = "604" ButtonBase.Click = "Window_Click" > <Grid> <StackPanel Margin = "20" ButtonBase.Click = "StackPanel_Click"> <StackPanel Margin = "10"> <TextBlock Name = "txt1" FontSize = "18" Margin = "5" Text = "This is a TextBlock 1" /> <TextBlock Name = "txt2" FontSize = "18" Margin = "5" Text = "This is a TextBlock 2" /> <TextBlock Name = "txt3" FontSize = "18" Margin = "5" Text = "This is a TextBlock 3" /> </StackPanel> <Button Margin = "10" Content = "Click me" Click = "Button_Click" Width = "80"/> </StackPanel> </Grid> </Window>
Вот код C # для реализации событий Click для Button, StackPanel и Window.
using System.Windows; namespace WPFRoutedEvents { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { txt1.Text = "Button is Clicked"; } private void StackPanel_Click(object sender, RoutedEventArgs e) { txt2.Text = "Click event is bubbled to Stack Panel"; } private void Window_Click(object sender, RoutedEventArgs e) { txt3.Text = "Click event is bubbled to Window"; } } }
Когда вы скомпилируете и выполните приведенный выше код, он выдаст следующее окно —
Когда вы нажимаете на кнопку, текстовые блоки обновляются, как показано ниже.
Если вы хотите остановить перенаправленное событие на каком-либо конкретном уровне, вам необходимо установить e.Handled = true;
Давайте изменим событие StackPanel_Click, как показано ниже —
private void StackPanel_Click(object sender, RoutedEventArgs e) { txt2.Text = "Click event is bubbled to Stack Panel"; e.Handled = true; }
При нажатии на кнопку вы увидите, что событие щелчка не будет направлено в окно и остановится на панели стека, а 3- й текстовый блок не будет обновлен.
Пользовательские маршрутизируемые события
В .NET Framework также можно определить настраиваемое перенаправленное событие. Чтобы определить настраиваемое перенаправленное событие в C #, необходимо выполнить приведенные ниже шаги.
-
Объявите и зарегистрируйте ваше перенаправленное событие с помощью системного вызова RegisterRoutedEvent.
-
Укажите стратегию маршрутизации, например Bubble, Tunnel или Direct.
-
Укажите обработчик событий.
Объявите и зарегистрируйте ваше перенаправленное событие с помощью системного вызова RegisterRoutedEvent.
Укажите стратегию маршрутизации, например Bubble, Tunnel или Direct.
Укажите обработчик событий.
Давайте рассмотрим пример, чтобы понять больше о пользовательских перенаправленных событиях. Следуйте инструкциям ниже
-
Создайте новый проект WPF с WPFCustomRoutedEvent
-
Щелкните правой кнопкой мыши ваше решение и выберите Добавить> Новый элемент …
-
Откроется следующее диалоговое окно, теперь выберите Custom Control (WPF) и назовите его MyCustomControl .
Создайте новый проект WPF с WPFCustomRoutedEvent
Щелкните правой кнопкой мыши ваше решение и выберите Добавить> Новый элемент …
Откроется следующее диалоговое окно, теперь выберите Custom Control (WPF) и назовите его MyCustomControl .
-
Нажмите кнопку Добавить , и вы увидите, что в ваше решение будут добавлены два новых файла (Themes / Generic.xaml и MyCustomControl.cs).
Нажмите кнопку Добавить , и вы увидите, что в ваше решение будут добавлены два новых файла (Themes / Generic.xaml и MyCustomControl.cs).
Следующий код XAML устанавливает стиль для пользовательского элемента управления в файле Generic.xaml.
<ResourceDictionary xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local = "clr-namespace:WPFCustomRoutedEvent"> <Style TargetType = "{x:Type local:MyCustomControl}"> <Setter Property = "Margin" Value = "50"/> <Setter Property = "Template"> <Setter.Value> <ControlTemplate TargetType = "{x:Type local:MyCustomControl}"> <Border Background = "{TemplateBinding Background}" BorderBrush = "{TemplateBinding BorderBrush}" BorderThickness = "{TemplateBinding BorderThickness}"> <Button x:Name = "PART_Button" Content = "Click Me" /> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
Ниже приведен код C # для класса MyCustomControl, который наследуется от класса Control, в котором для настраиваемого элемента управления создается настраиваемое перенаправленное событие Click.
using System.Windows; using System.Windows.Controls; namespace WPFCustomRoutedEvent { public class MyCustomControl : Control { static MyCustomControl() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl))); } public override void OnApplyTemplate() { base.OnApplyTemplate(); //demo purpose only, check for previous instances and remove the handler first var button = GetTemplateChild("PART_Button") as Button; if (button ! = null) button.Click + = Button_Click; } void Button_Click(object sender, RoutedEventArgs e) { RaiseClickEvent(); } public static readonly RoutedEvent ClickEvent = EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyCustomControl)); public event RoutedEventHandler Click { add { AddHandler(ClickEvent, value); } remove { RemoveHandler(ClickEvent, value); } } protected virtual void RaiseClickEvent() { RoutedEventArgs args = new RoutedEventArgs(MyCustomControl.ClickEvent); RaiseEvent(args); } } }
Вот пользовательская реализация перенаправленного события в C #, которая будет отображать окно сообщения, когда пользователь щелкает по нему.
using System.Windows; namespace WPFCustomRoutedEvent { // <summary> // Interaction logic for MainWindow.xaml // </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void MyCustomControl_Click(object sender, RoutedEventArgs e) { MessageBox.Show("It is the custom routed event of your custom control"); } } }
Вот реализация в MainWindow.xaml для добавления пользовательского элемента управления с перенаправленным событием Click.
<Window x:Class = "WPFCustomRoutedEvent.MainWindow" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local = "clr-namespace:WPFCustomRoutedEvent" Title = "MainWindow" Height = "350" Width = "604"> <Grid> <local:MyCustomControl Click = "MyCustomControl_Click" /> </Grid> </Window>
Когда приведенный выше код компилируется и выполняется, он создаст следующее окно, которое содержит пользовательский элемент управления.
Когда вы нажимаете на пользовательский элемент управления, он выдаст следующее сообщение.