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 3º 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.