Olayları önizleme (WPF .NET)
Tünel olayları olarak da bilinen önizleme olayları, uygulama kök öğesinden olayı tetikleyen öğeye öğe ağacı boyunca aşağı doğru geçen yönlendirilmiş olaylardır. Olay oluşturan öğesi, olay verilerinde olarak Source bildirilir. Tüm olay senaryoları önizleme olaylarını desteklemez veya gerektirmez. Bu makalede önizleme olaylarının nerede olduğu ve uygulamaların veya bileşenlerin bunlarla nasıl etkileşim kurabileceği açıklanmaktadır. Önizleme olayı oluşturma hakkında bilgi için bkz . Özel yönlendirilmiş olay oluşturma.
Önkoşullar
Makalede, yönlendirilen olaylar hakkında temel bilgiler edindiğiniz ve Yönlendirilen olaylara genel bakış makalesini okuduğunuz varsayılır. Bu makaledeki örnekleri takip etmek için, Genişletilebilir Uygulama biçimlendirme dili (XAML) hakkında bilgi sahibi olmanız ve Windows Presentation Foundation (WPF) uygulamalarının nasıl yazıldığından haberdar olmanız yardımcı olur.
İşlendi olarak işaretlenmiş olayları önizleme
Önizleme olaylarını olay verilerinde işlenecek şekilde işaretlerken dikkatli olun. Bir önizleme olayını yükselten öğe dışındaki bir öğede işlenmek üzere işaretlemek, onu yükselten öğenin olayı işlemesini engelleyebilir. Bazen önizleme olaylarının işlendiğinde işaretlenmesi kasıtlı olarak gerçekleştirilir. Örneğin, bileşik denetim tek tek bileşenler tarafından tetiklenen olayları bastırabilir ve bunları tam denetim tarafından tetiklenen olaylarla değiştirebilir. Denetim için özel olaylar, bileşen durumu ilişkilerine göre özelleştirilmiş olay verileri ve tetikleyici sağlayabilir.
Giriş olayları için olay verileri, her olayın hem önizleme hem de önizleme dışı (kabarcık oluşturma) eşdeğerleri tarafından paylaşılır. Bir giriş olayını işlenmiş olarak işaretlemek için bir önizleme olayı sınıf işleyicisi kullanırsanız, kabarcık oluşturma giriş olayı için sınıf işleyicileri genellikle çağrılamaz. Öte yandan, bir olayı işlenmiş olarak işaretlemek için bir önizleme olay örneği işleyicisi kullanırsanız, kabarcık giriş olayının örnek işleyicileri genellikle çağrılmazsınız. Bir olay işlendi olarak işaretlenmiş olsa bile çağrılacak sınıf ve örnek işleyicilerini yapılandırabilirsiniz ancak bu işleyici yapılandırması yaygın değildir. Sınıf işleme ve önizleme olaylarıyla ilişkisi hakkında daha fazla bilgi için bkz . Yönlendirilen olayları işlenmiş olarak işaretleme ve sınıf işleme.
Not
Önizleme olaylarının tümü olayları tünellemez. Örneğin, PreviewMouseLeftButtonDown giriş olayı öğe ağacı boyunca aşağı doğru bir yol izler, ancak yoldaki her UIElement biri tarafından tetiklenen ve yeniden değerlendirilen doğrudan yönlendirilmiş bir olaydır.
Denetimler tarafından olay gizlemeyi geçici olarak çözme
Bazı bileşik denetimler, özelleştirilmiş bir üst düzey olayla değiştirmek için bileşen düzeyinde giriş olaylarını gizler. Örneğin, WPF ButtonBase kabarcık giriş olayını yönteminde OnMouseLeftButtonDown işlenmiş olarak işaretler MouseLeftButtonDown ve olayı tetiklerClick. Olay MouseLeftButtonDown
ve olay verileri öğe ağacı yolu boyunca devam eder, ancak olay olay verilerinde olarak Handled işaretlendiğinden, yalnızca işlenen olaylara yanıt verecek şekilde yapılandırılmış işleyiciler çağrılır.
Uygulamanızın köküne yönelik diğer öğelerin işlendi olarak işaretlenmiş yönlendirilmiş bir olayı işlemesini istiyorsanız şunlardan birini yapabilirsiniz:
yöntemini çağırarak ve parametresini UIElement.AddHandler(RoutedEvent, Delegate, Boolean)
handledEventsToo
true
olarak ayarlayarak işleyicileri ekleyin. Bu yaklaşım, ekleyecek öğeye bir nesne başvurusu aldıktan sonra olay işleyicisinin arka planda koda eklenmesini gerektirir.İşlendi olarak işaretlenen olay bir kabarcık olayıysa, varsa eşdeğer önizleme olayı için işleyiciler ekleyin. Örneğin, bir denetim olayı bastırıyorsa MouseLeftButtonDown , bunun yerine olay için PreviewMouseLeftButtonDown bir işleyici ekleyebilirsiniz. Bu yaklaşım yalnızca hem tünel hem de kabarcık yönlendirme stratejileri uygulayan ve olay verilerini paylaşan temel öğe giriş olayları için çalışır.
Aşağıdaki örnek, öğesini içeren TextBoxadlı componentWrapper
bir ilkel özel denetim uygular. Denetim adlı outerStackPanel
bir StackPanel öğesine eklenir.
<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>
Denetim, componentWrapper
bir tuş vuruşu gerçekleştiğinde KeyDown bileşeni tarafından TextBox
tetiklenen kabarcık olayını dinler. Bu durumla ilgili componentWrapper
denetim:
Kabarcıklanan
KeyDown
yönlendirilmiş olayı, gizlenmek için işlenme olarak işaretler. Sonuç olarak, yalnızcaouterStackPanel
işlenenKeyDown
olaylara yanıt vermek için arka planda kod içinde yapılandırılmış işleyici tetiklenmiş olur.outerStackPanel
Olaylar içinKeyDown
XAML'ye eklenen işleyici çağrılmıyor.adlı
CustomKey
özel bir kabarcıklama yönlendirilmiş olayı oluşturur ve bu olay işleyicisiniouterStackPanel
CustomKey
tetikler.
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
Örnekte, öğesine bağlı bir olay işleyicisini çağırmak için gizlenen yönlendirilmiş KeyDown
olayı almak için iki geçici çözüm gösterilmektedir outerStackPanel
:
öğesine bir PreviewKeyDown olay işleyicisi
outerStackPanel
ekleyin. Bir önizleme girişi yönlendirilmiş olay eşdeğer kabarcık yönlendirilmiş olayından önce olduğundan, örnekteki işleyici,PreviewKeyDown
paylaşılan olay verileri aracılığıyla hem önizleme hem de kabarcık oluşturma olaylarını bastıran işleyicininKeyDown
önünde çalışır.parametresi olarak ayarlanmış
true
arka plandahandledEventsToo
yöntemini kullanarak UIElement.AddHandler(RoutedEvent, Delegate, Boolean) öğesine birKeyDown
olay işleyicisiouterStackPanel
ekleyin.
Not
Giriş olaylarının önizleme veya önizleme dışı eşdeğerlerinin işlenmek üzere işaretlenmesi, denetimin bileşenleri tarafından oluşturulan olayları gizlemeye yönelik stratejilerdir. Kullandığınız yaklaşım, uygulama gereksinimlerinize bağlıdır.
Ayrıca bkz.
.NET Desktop feedback