WPF - Eventos Roteados

UMA routed eventé um tipo de evento que pode invocar manipuladores em vários ouvintes em uma árvore de elementos, em vez de apenas o objeto que gerou o evento. É basicamente um evento CLR suportado por uma instância da classe Routed Event. Ele é registrado no sistema de eventos WPF. RoutedEvents têm três estratégias de roteamento principais que são as seguintes -

  • Evento Direto
  • Evento Borbulhante
  • Evento Túnel

Evento Direto

Um evento direto é semelhante a eventos em formulários do Windows que são gerados pelo elemento no qual o evento é originado.

Ao contrário de um evento CLR padrão, os eventos roteados diretos suportam o tratamento de classes e podem ser usados ​​em Event Setters e Event Triggers dentro do seu estilo de controle personalizado.

Um bom exemplo de um evento direto seria o evento MouseEnter.

Evento Borbulhante

Um evento de bolhas começa com o elemento onde o evento é originado. Em seguida, ele sobe na árvore visual até o elemento superior da árvore visual. Portanto, no WPF, o elemento superior é provavelmente uma janela.

Evento Túnel

Os manipuladores de eventos na raiz da árvore de elementos são chamados e, em seguida, o evento viaja pela árvore visual para todos os nós filhos até atingir o elemento no qual o evento foi originado.

A diferença entre um evento de bubbling e de tunneling é que um evento de tunneling sempre começa com uma visualização.

Em um aplicativo WPF, os eventos são frequentemente implementados como um par tunelamento / borbulhamento. Portanto, você terá uma visualização do MouseDown e um evento MouseDown.

A seguir, é fornecido um exemplo simples de um evento roteado no qual um botão e três blocos de texto são criados com algumas propriedades e eventos.

<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>

Aqui está o código C # para a implementação de eventos Click para Button, StackPanel e 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"; 
      }
		
   } 
}

Quando você compila e executa o código acima, ele irá produzir a seguinte janela -

Ao clicar no botão, os blocos de texto serão atualizados, conforme mostrado abaixo.

Se quiser interromper o evento roteado em qualquer nível específico, será necessário definir o e.Handled = true;

Vamos mudar o StackPanel_Click evento como mostrado abaixo -

private void StackPanel_Click(object sender, RoutedEventArgs e) { 
   txt2.Text = "Click event is bubbled to Stack Panel"; 
   e.Handled = true; 
}

Ao clicar no botão, você observará que o evento de clique não será roteado para a janela e irá parar no painel de pilha e o bloco de texto não será atualizado.

Eventos roteados personalizados

Na estrutura .NET, o evento roteado personalizado também pode ser definido. Você precisa seguir as etapas fornecidas a seguir para definir um evento roteado personalizado em C #.

  • Declare e registre seu evento roteado com a chamada de sistema RegisterRoutedEvent.

  • Especifique a estratégia de roteamento, ou seja, bolha, túnel ou direto.

  • Fornece o manipulador de eventos.

Vamos dar um exemplo para entender mais sobre eventos roteados personalizados. Siga as etapas abaixo -

  • Crie um novo projeto WPF com WPFCustomRoutedEvent

  • Clique com o botão direito na sua solução e selecione Adicionar> Novo Item ...

  • A seguinte caixa de diálogo será aberta, agora selecione Custom Control (WPF) e nomeá-lo MyCustomControl.

  • Clique no Add botão e você verá que dois novos arquivos (Themes / Generic.xaml e MyCustomControl.cs) serão adicionados à sua solução.

O código XAML a seguir define o estilo do controle personalizado no arquivo 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>

A seguir está o código C # para o MyCustomControl class que herda do Control class em que um Click de evento roteado personalizado é criado para o controle personalizado.

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); 
      }
		
   } 
}

Aqui está a implementação de evento roteado personalizado em C #, que exibirá uma caixa de mensagem quando o usuário clicar nela.

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"); 
      } 
		
   } 
}

Aqui está a implementação em MainWindow.xaml para adicionar o controle personalizado com um evento roteado 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>

Quando o código acima é compilado e executado, ele produzirá a seguinte janela que contém um controle personalizado.

Quando você clica no controle personalizado, a seguinte mensagem é exibida.