考虑为Button添加ClickEvent-和PreviewMouseLeftButtonDown-Handler
<Button x:Name="button"
Click="Button_Click"
PreviewMouseLeftButtonDown="Button_PreviewMouseLeftButtonDown">
</Button>
单击Button时,首先触发PreviewMouseLeftButtonDown,然后触发Click-Event。
如果在预览...-事件中设置e.Handled = true
,则不再处理Click-Event。
但是,现在让我们想一想MouseLeftButtonDownEvent 首先,此事件的路由策略是直接的。也就是说,它会针对每个控件重新提升。相比之下,预览...... - 事件是隧道,点击事件正在冒泡 其次,只有在注册处理程序时才添加MouseLeftButtonDownEventHandler,以便甚至为已经处理的事件调用它,如以下代码摘录所示。
button.AddHandler(MouseLeftButtonDownEvent,
new MouseButtonEventHandler(Button_MouseLeftButtonDown),
true);
我编写了一个测试应用程序,有一个按钮,并为每个事件添加了一个处理程序。调用事件处理程序时,它会将一些信息写入文本块。
e.Handled = true
添加到Preview ...- EventHandler时,只调用此事件处理程序。即使是鼠标...... - EventHandler也没有被引发,尽管我已将UIElement.AddHandler handledEventsToo
设置为true。e.Handled = true
添加到Mouse ...- EventHandler时,将调用所有三个事件处理程序。这对我没有任何意义。鼠标...- EventHandlers不会影响Click-EventHandlers,但预览...- EventHandlers会影响鼠标...-和Click-EventHandlers。
甚至'强制'处理事件也失败了鼠标......- EventHandler。
实际上,我从未想过不同类型的事件处理程序会影响彼此。我的理解是,如果我有一个预览...... - 事件和点击事件,这些都是独立的。
那么,我错过了什么?
以下是非常简单的示例代码:
XAML:
<DockPanel>
<Border x:Name="border" DockPanel.Dock="Top" Height="50"
BorderBrush="Gray" BorderThickness="1">
<StackPanel x:Name="stackpanel" Background="LightGray"
Orientation="Horizontal" HorizontalAlignment="Center">
<Button x:Name="button" Width="Auto"
PreviewMouseLeftButtonDown="Button_PreviewMouseLeftButtonDown">
Click Me
</Button>
</StackPanel>
</Border>
<Border DockPanel.Dock="Bottom" BorderBrush="Gray" BorderThickness="1">
<ScrollViewer>
<TextBlock x:Name="textBlock" TextWrapping="Wrap"/>
</ScrollViewer>
</Border>
</DockPanel>
代码隐藏:
public MainWindow()
{
InitializeComponent();
button.AddHandler(MouseLeftButtonDownEvent, new MouseButtonEventHandler(Button_MouseLeftButtonDown), true);
button.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click), true);
stackpanel.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click), true /*false*/ );
}
private void Output(object sender, RoutedEventArgs e)
{
textBlock.Text += "RoutedEvent: " + e.RoutedEvent + "\n";
textBlock.Text += "Sender: " + sender + "\n";
textBlock.Text += "Source: " + e.Source + "\n";
textBlock.Text += "OriginalSource: " + e.OriginalSource + "\n" + "\n";
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// e.Handled = true;
Output(sender, e);
}
private void Button_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
// e.Handled = true;
Output(sender, e);
}
private void Button_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Output(sender, e);
}
答案 0 :(得分:2)
我从未想过不同类型的事件处理程序会相互影响
您大多是正确的,因为这种情况非常罕见,但您可以在MSDN上的Preview Events页面找到答案。从链接页面:
例如,Windows Presentation Foundation(WPF)按钮禁止Button或其复合元素引发的MouseLeftButtonDown和MouseLeftButtonDown冒泡事件,以支持捕获鼠标并引发始终由Button本身引发的Click事件。事件及其数据仍沿着路径继续,但由于Button将事件数据标记为Handled,因此仅调用特定表明它们应在handleEventsToo案例中操作的事件的处理程序。
此外,你说过这个:
当我向鼠标...- EventHandler添加e.Handled = true时,会调用所有三个事件处理程序
这是预期的,因为在冒泡事件处理程序中设置e.Handled
将不执行任何操作......在事件离开处理程序代码之后,没有任何内容会读取该值。 e.Handled
主要用于隧道事件处理程序,以阻止事件进一步路由。再次,从链接页面:
对于具体的输入事件,预览事件还与等效的冒泡事件共享事件数据实例。如果使用Preview事件类处理程序标记处理的输入事件,则不会调用冒泡输入事件类处理程序。或者,如果使用预览事件实例处理程序来标记处理的事件,则通常不会调用冒泡事件的处理程序。