Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Zdarzenia podglądu, nazywane również zdarzeniami tunelowania, to są zdarzenia routowane przechodzące w dół przez drzewo elementów, od elementu głównego aplikacji do elementu, który zgłosił zdarzenie. Element, który zgłasza zdarzenie, jest zgłaszany jako Source w danych zdarzenia. Nie wszystkie scenariusze zdarzeń obsługują lub wymagają zdarzeń w wersji zapoznawczej. W tym artykule opisano, gdzie istnieją zdarzenia w wersji zapoznawczej oraz jak aplikacje lub składniki mogą z nimi współdziałać. Aby uzyskać informacje o tym, jak utworzyć zdarzenie podglądowe, zobacz Jak utworzyć niestandardowe zdarzenie kierowane.
Wymagania wstępne
Artykuł zakłada podstawową znajomość zdarzeń trasowanych i że przeczytałeś Przegląd zdarzeń trasowanych. Aby postępować zgodnie z przykładami w tym artykule, warto zapoznać się z językiem Extensible Application Markup Language (XAML) i wiedzieć, jak pisać aplikacje programu Windows Presentation Foundation (WPF).
Podgląd zdarzeń oznaczonych jako przetwarzane
Należy zachować ostrożność podczas oznaczania zdarzeń podglądu, które są obsługiwane w danych zdarzeń. Oznaczenie zapowiedzi zdarzenia jako obsługiwanej przez element inny niż ten, który je wywołał, może uniemożliwić temu drugiemu elementowi obsługę zdarzenia. Czasami oznaczanie zdarzeń podglądu jako obsłużonych jest zamierzone. Na przykład kontrolka złożona może pomijać zdarzenia wywoływane przez poszczególne składniki i zastępować je zdarzeniami zgłoszonymi przez pełną kontrolkę. Zdarzenia niestandardowe dla kontrolki mogą udostępniać dostosowane dane zdarzeń i wyzwalacz na podstawie relacji stanu składnika.
W przypadku zdarzeń wejściowych dane zdarzeń są współużytkowane zarówno przez wersję podglądową, jak i przez odpowiadającą jej niepodglądową wersję (bąbelkową). Jeśli używasz procedury obsługi zdarzeń w wersji zapoznawczej do oznaczania zdarzenia wejściowego jako obsługiwanego, programy obsługi klas dla zdarzenia wejściowego bubbling zwykle nie będą wywoływane. Lub jeśli używasz programu obsługi zdarzeń w wersji zapoznawczej do oznaczania zdarzenia jako obsługiwanego, programy obsługi wystąpień dla zdarzenia wejściowego bubbling zwykle nie będą wywoływane. Mimo że można skonfigurować programy obsługi klas i wystąpień, które mogą być wywołane, nawet jeśli zdarzenie jest oznaczone jako obsługiwane, taka konfiguracja nie jest powszechna. Aby uzyskać więcej informacji na temat obsługi klas i jej związku ze zdarzeniami podglądu, zobacz Oznaczanie zdarzeń routowanych jako obsługiwane i obsługa klas.
Uwaga / Notatka
Nie wszystkie zdarzenia w wersji zapoznawczej to zdarzenia tunelowania . Na przykład zdarzenie wejściowe PreviewMouseLeftButtonDown podąża trasą w dół przez drzewo elementów, ale jest zdarzeniem kierowanym bezpośrednio, które jest wywoływane i wzbudzane ponownie przez każdy element UIElement w trasie.
Obejście tłumienia zdarzeń przez kontrolki
Niektóre kontrolki złożone pomijają zdarzenia wejściowe na poziomie składnika, aby zastąpić je niestandardowym zdarzeniem wysokiego poziomu. Na przykład, WPF ButtonBase oznacza zdarzenie wejściowe "bubbling" jako obsłużone w swojej metodzie OnMouseLeftButtonDown i zgłasza zdarzenie Click. Zdarzenie MouseLeftButtonDown i jego dane zdarzenia nadal są kontynuowane wzdłuż trasy drzewa elementów, ale ponieważ zdarzenie jest oznaczone jako Handled w danych zdarzenia, wywoływane są tylko programy obsługi skonfigurowane do reagowania na obsługiwane zdarzenia.
Jeśli chcesz, aby inne elementy bliżej korzenia Twojej aplikacji przejmowały obsługę zdarzeń kierowanych, które są oznaczone jako obsługiwane, możesz wykonać następujące czynności:
Dołącz procedury obsługi poprzez wywołanie metody UIElement.AddHandler(RoutedEvent, Delegate, Boolean) i ustawienie parametru
handledEventsToonatrue. Takie podejście wymaga dołączenia procedury obsługi zdarzeń w kodzie za kulisami, po uzyskaniu odwołania do obiektu elementu, do którego będzie dołączony.Jeśli zdarzenie oznaczone jako obsługiwane jest zdarzeniem propagującym się, dołącz procedury obsługi dla odpowiedniego zdarzenia podglądu, jeśli jest dostępne. Jeśli na przykład kontrolka pomija zdarzenie MouseLeftButtonDown, możesz dołączyć procedurę obsługi dla zdarzenia PreviewMouseLeftButtonDown. Takie podejście działa tylko w przypadku zdarzeń wejściowych elementów podstawowych, które implementują strategie tunelowania i propagacji routingu oraz udostępniają dane zdarzeń.
Poniższy przykład implementuje podstawową kontrolkę niestandardową componentWrapper, która zawiera TextBox. Kontrolka jest dodawana do StackPanel o nazwie outerStackPanel.
<StackPanel Name="outerStackPanel"
VerticalAlignment="Center"
custom:ComponentWrapper.CustomKey="Handler_PrintEventInfo"
TextBox.KeyDown="Handler_PrintEventInfo"
TextBox.PreviewKeyDown="Handler_PrintEventInfo" >
<custom:ComponentWrapper
x:Name="componentWrapper"
TextBox.KeyDown="ComponentWrapper_KeyDown"
custom:ComponentWrapper.CustomKey="Handler_PrintEventInfo"
HorizontalAlignment="Center">
<TextBox Name="componentTextBox" Width="200" KeyDown="Handler_PrintEventInfo" />
</custom:ComponentWrapper>
</StackPanel>
Kontrolka componentWrapper nasłuchuje KeyDown zdarzenia bubbling zgłoszonego przez jego TextBox składnik za każdym razem, gdy wystąpi naciśnięcie. W tym przypadku kontrolka componentWrapper :
Oznacza rozsyłane
KeyDownzdarzenie kierowane zgodnie z procedurą obsługi, aby je pominąć. W związku z tym, wyzwalany jest tylkoouterStackPanelobsługujący skonfigurowany w kodzie zaplecza do reagowania na obsługiwaneKeyDownzdarzenia. Procedura obsługi zdarzeńouterStackPanel, dołączona w XAML dla zdarzeńKeyDown, nie jest wywoływana.Wywołuje niestandardowe zdarzenie rozsyłane na trasie o nazwie
CustomKey, które uruchamia procedurę obsługiouterStackPaneldla zdarzeniaCustomKey.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Attach a handler on outerStackPanel that will be invoked by handled KeyDown events.
outerStackPanel.AddHandler(KeyDownEvent, new RoutedEventHandler(Handler_PrintEventInfo),
handledEventsToo: true);
}
private void ComponentWrapper_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
Handler_PrintEventInfo(sender, e);
Debug.WriteLine("KeyDown event marked as handled on componentWrapper.\r\n" +
"CustomKey event raised on componentWrapper.");
// Mark the event as handled.
e.Handled = true;
// Raise the custom click event.
componentWrapper.RaiseCustomRoutedEvent();
}
private void Handler_PrintEventInfo(object sender, System.Windows.Input.KeyEventArgs e)
{
string senderName = ((FrameworkElement)sender).Name;
string sourceName = ((FrameworkElement)e.Source).Name;
string eventName = e.RoutedEvent.Name;
string handledEventsToo = e.Handled ? " Parameter handledEventsToo set to true." : "";
Debug.WriteLine($"Handler attached to {senderName} " +
$"triggered by {eventName} event raised on {sourceName}.{handledEventsToo}");
}
private void Handler_PrintEventInfo(object sender, RoutedEventArgs e)
{
string senderName = ((FrameworkElement)sender).Name;
string sourceName = ((FrameworkElement)e.Source).Name;
string eventName = e.RoutedEvent.Name;
string handledEventsToo = e.Handled ? " Parameter handledEventsToo set to true." : "";
Debug.WriteLine($"Handler attached to {senderName} " +
$"triggered by {eventName} event raised on {sourceName}.{handledEventsToo}");
}
// Debug output:
//
// Handler attached to outerStackPanel triggered by PreviewKeyDown event raised on componentTextBox.
// Handler attached to componentTextBox triggered by KeyDown event raised on componentTextBox.
// Handler attached to componentWrapper triggered by KeyDown event raised on componentTextBox.
// KeyDown event marked as handled on componentWrapper.
// CustomKey event raised on componentWrapper.
// Handler attached to componentWrapper triggered by CustomKey event raised on componentWrapper.
// Handler attached to outerStackPanel triggered by CustomKey event raised on componentWrapper.
// Handler attached to outerStackPanel triggered by KeyDown event raised on componentTextBox. Parameter handledEventsToo set to true.
}
public class ComponentWrapper : StackPanel
{
// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent CustomKeyEvent =
EventManager.RegisterRoutedEvent(
name: "CustomKey",
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(ComponentWrapper));
// Provide CLR accessors for assigning an event handler.
public event RoutedEventHandler CustomKey
{
add { AddHandler(CustomKeyEvent, value); }
remove { RemoveHandler(CustomKeyEvent, value); }
}
public void RaiseCustomRoutedEvent()
{
// Create a RoutedEventArgs instance.
RoutedEventArgs routedEventArgs = new(routedEvent: CustomKeyEvent);
// Raise the event, which will bubble up through the element tree.
RaiseEvent(routedEventArgs);
}
}
Partial Public Class MainWindow
Inherits Window
Public Sub New()
InitializeComponent()
' Attach a handler on outerStackPanel that will be invoked by handled KeyDown events.
outerStackPanel.[AddHandler](KeyDownEvent, New RoutedEventHandler(AddressOf Handler_PrintEventInfo),
handledEventsToo:=True)
End Sub
Private Sub ComponentWrapper_KeyDown(sender As Object, e As KeyEventArgs)
Handler_PrintEventInfo(sender, e)
Debug.WriteLine("KeyDown event marked as handled on componentWrapper." &
vbCrLf & "CustomKey event raised on componentWrapper.")
' Mark the event as handled.
e.Handled = True
' Raise the custom click event.
componentWrapper.RaiseCustomRoutedEvent()
End Sub
Private Sub Handler_PrintEventInfo(sender As Object, e As KeyEventArgs)
Dim senderName As String = CType(sender, FrameworkElement).Name
Dim sourceName As String = CType(e.Source, FrameworkElement).Name
Dim eventName As String = e.RoutedEvent.Name
Dim handledEventsToo As String = If(e.Handled, " Parameter handledEventsToo set to true.", "")
Debug.WriteLine($"Handler attached to {senderName} " &
$"triggered by {eventName} event raised on {sourceName}.{handledEventsToo}")
End Sub
Private Sub Handler_PrintEventInfo(sender As Object, e As RoutedEventArgs)
Dim senderName As String = CType(sender, FrameworkElement).Name
Dim sourceName As String = CType(e.Source, FrameworkElement).Name
Dim eventName As String = e.RoutedEvent.Name
Dim handledEventsToo As String = If(e.Handled, " Parameter handledEventsToo set to true.", "")
Debug.WriteLine($"Handler attached to {senderName} " &
$"triggered by {eventName} event raised on {sourceName}.{handledEventsToo}")
End Sub
' Debug output
'
' Handler attached to outerStackPanel triggered by PreviewKeyDown event raised on componentTextBox.
' Handler attached to componentTextBox triggered by KeyDown event raised on componentTextBox.
' Handler attached to componentWrapper triggered by KeyDown event raised on componentTextBox.
' KeyDown event marked as handled on componentWrapper.
' CustomKey event raised on componentWrapper.
' Handler attached to componentWrapper triggered by CustomKey event raised on componentWrapper.
' Handler attached to outerStackPanel triggered by CustomKey event raised on componentWrapper.
' Handler attached to outerStackPanel triggered by KeyDown event raised on componentTextBox. Parameter handledEventsToo set to true.
End Class
Public Class ComponentWrapper
Inherits StackPanel
' Register a custom routed event with the Bubble routing strategy.
Public Shared ReadOnly CustomKeyEvent As RoutedEvent =
EventManager.RegisterRoutedEvent(
name:="CustomKey",
routingStrategy:=RoutingStrategy.Bubble,
handlerType:=GetType(RoutedEventHandler),
ownerType:=GetType(ComponentWrapper))
' Provide CLR accessors to support event handler assignment.
Public Custom Event CustomKey As RoutedEventHandler
AddHandler(value As RoutedEventHandler)
[AddHandler](CustomKeyEvent, value)
End AddHandler
RemoveHandler(value As RoutedEventHandler)
[RemoveHandler](CustomKeyEvent, value)
End RemoveHandler
RaiseEvent(sender As Object, e As RoutedEventArgs)
[RaiseEvent](e)
End RaiseEvent
End Event
Public Sub RaiseCustomRoutedEvent()
' Create a RoutedEventArgs instance & raise the event,
' which will bubble up through the element tree.
Dim routedEventArgs As New RoutedEventArgs(routedEvent:=CustomKeyEvent)
[RaiseEvent](routedEventArgs)
End Sub
End Class
W tym przykładzie przedstawiono dwa obejścia umożliwiające pobranie pominiętego KeyDown zdarzenia kierowanego w celu wywołania procedury obsługi zdarzeń dołączonej do elementu outerStackPanel:
Dołącz procedurę obsługi zdarzeń PreviewKeyDown do programu
outerStackPanel. Ponieważ zdarzenie wstępnego skierowania wejścia poprzedza równoważne zdarzenie kaskadowe, procedura obsługi w przykładzie jest uruchamiana przed procedurą obsługi tłumiącą zarówno zdarzenia podglądu, jak i kaskadowe za pośrednictwem ich udostępnionych danych zdarzenia.Dołącz procedurę obsługi zdarzeń
KeyDowndoouterStackPanelprzy użyciu metody UIElement.AddHandler(RoutedEvent, Delegate, Boolean) w kodzie za pomocą parametru ustawionego natruehandledEventsToo.
Uwaga / Notatka
Oznaczanie podglądu lub niepodglądowych odpowiedników zdarzeń wejściowych jako obsługiwanych to dwie strategie pomijania zdarzeń zgłaszanych przez składniki kontrolki. Używane podejście zależy od wymagań aplikacji.
Zobacz także
.NET Desktop feedback