WPF - zdarzenia kierowane
ZA routed eventjest typem zdarzenia, które może wywołać procedury obsługi wielu detektorów w drzewie elementów, a nie tylko obiekt, który wywołał zdarzenie. Zasadniczo jest to zdarzenie CLR obsługiwane przez instancję klasy Routed Event. Jest zarejestrowany w systemie zdarzeń WPF. RoutedEvents mają trzy główne strategie routingu, które są następujące:
- Wydarzenie bezpośrednie
- Wydarzenie propagujące
- Wydarzenie w tunelu
Wydarzenie bezpośrednie
Zdarzenie bezpośrednie jest podobne do zdarzeń w formularzach systemu Windows, które są wywoływane przez element, z którego pochodzi zdarzenie.
W przeciwieństwie do standardowego zdarzenia CLR, zdarzenia kierowane bezpośrednio obsługują obsługę klas i mogą być używane w ustawieniach zdarzeń i wyzwalaczach zdarzeń w ramach Twojego stylu kontroli niestandardowej.
Dobrym przykładem bezpośredniego zdarzenia byłoby zdarzenie MouseEnter.
Wydarzenie propagujące
Zdarzenie propagacji zaczyna się od elementu, z którego pochodzi zdarzenie. Następnie podróżuje w górę drzewa wizualnego do najwyższego elementu w drzewie wizualnym. Tak więc w WPF najwyższym elementem jest najprawdopodobniej okno.
Wydarzenie w tunelu
Procedury obsługi zdarzeń w katalogu głównym drzewa elementów są wywoływane, a następnie zdarzenie przechodzi w dół drzewa wizualnego do wszystkich węzłów podrzędnych, aż osiągnie element, z którego pochodzi zdarzenie.
Różnica między zdarzeniem propagacji a zdarzeniem tunelowania polega na tym, że zdarzenie tunelowania zawsze zaczyna się od podglądu.
W aplikacji WPF zdarzenia są często implementowane jako para tunelowania / propagacji. Będziesz więc mieć podgląd MouseDown, a następnie zdarzenie MouseDown.
Poniżej podano prosty przykład zdarzenia Routed, w którym przycisk i trzy bloki tekstu są tworzone z pewnymi właściwościami i zdarzeniami.
<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>
Oto kod C # dla implementacji zdarzeń Click dla Button, StackPanel i 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";
}
}
}
Kiedy kompilujesz i wykonujesz powyższy kod, wygeneruje on następujące okno -
Po kliknięciu przycisku bloki tekstu zostaną zaktualizowane, jak pokazano poniżej.
Jeśli chcesz zatrzymać kierowane zdarzenie na jakimkolwiek określonym poziomie, musisz ustawić e.Handled = true;
Zmieńmy StackPanel_Click zdarzenie, jak pokazano poniżej -
private void StackPanel_Click(object sender, RoutedEventArgs e) {
txt2.Text = "Click event is bubbled to Stack Panel";
e.Handled = true;
}
Po kliknięciu na przycisk, można zaobserwować, że zdarzenie click nie będą kierowane do okna i zatrzyma się na StackPanel i 3 rd blok tekstu nie zostaną zaktualizowane.
Niestandardowe zdarzenia kierowane
W środowisku .NET można również zdefiniować niestandardowe zdarzenia kierowane. Aby zdefiniować niestandardowe zdarzenie kierowane w języku C #, należy wykonać kroki podane poniżej.
Zadeklaruj i zarejestruj swoje zdarzenie kierowane za pomocą wywołania systemowego RegisterRoutedEvent.
Określ strategię routingu, np. Bubble, Tunnel lub Direct.
Podaj procedurę obsługi zdarzeń.
Weźmy przykład, aby dowiedzieć się więcej o niestandardowych zdarzeniach kierowanych. Wykonaj czynności podane poniżej -
Utwórz nowy projekt WPF za pomocą WPFCustomRoutedEvent
Kliknij prawym przyciskiem myszy rozwiązanie i wybierz Dodaj> Nowy element ...
Otworzy się następujące okno dialogowe, teraz wybierz Custom Control (WPF) i nazwij to MyCustomControl.
Kliknij Add i zobaczysz, że dwa nowe pliki (Themes / Generic.xaml i MyCustomControl.cs) zostaną dodane do twojego rozwiązania.
Poniższy kod XAML ustawia styl kontrolki niestandardowej w pliku 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>
Poniżej podano kod C # dla MyCustomControl class który dziedziczy z Control class w którym niestandardowe kierowane zdarzenie Click jest tworzone dla kontrolki niestandardowej.
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);
}
}
}
Oto implementacja zdarzenia kierowanego niestandardowo w C #, która wyświetli okno komunikatu, gdy użytkownik go kliknie.
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");
}
}
}
Oto implementacja w MainWindow.xaml, aby dodać kontrolkę niestandardową ze zdarzeniem kierowanym 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>
Gdy powyższy kod zostanie skompilowany i wykonany, utworzy następujące okno zawierające niestandardową kontrolkę.
Po kliknięciu kontrolki niestandardowej wyświetli się następujący komunikat.