Учебники

WPF — маршрутизируемые события

Маршрутизируемое событие — это тип события, которое может вызывать обработчики для нескольких слушателей в дереве элементов, а не только для объекта, вызвавшего событие. Это в основном событие 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>

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

пользовательский контроль

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