显示 MessageBox 时,MouseDown 事件不会冒泡到 Button Click 事件
MouseDown event not bubbling up to Button Click event when displaying a MessageBox
版本 1 XAML 代码:
<Button Padding="10" Background="Green" Width="500">
<StackPanel MouseDown="StackPanel_MouseDown" Background="Gray" Width="500" Height="300">
<Ellipse MouseDown="Ellipse_MouseDown" Width="100" Height="100" Fill="Red"></Ellipse>
</StackPanel>
</Button>
版本 1 代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("This is the Ellipse");
// Shows this MessageBox.
}
private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("This is the StackPanel");
// Also shows this MessageBox.
}
}
当我有 2 个 MouseDown
事件时,一个用于 Ellipse
,一个用于 StackPanel
,无论我是否使用 MessageBox
,它仍然会冒泡在显示第一个 MessageBox
.
之后
但是,如果我在 Button
上有 Click
事件,它将停止工作。
版本 2 XAML代码:
<Button Padding="10" Background="Green" Width="500" Click="Button_Click">
<StackPanel Background="Gray" Width="500" Height="300">
<Ellipse MouseDown="Ellipse_MouseDown" Width="100" Height="100" Fill="Red"></Ellipse>
</StackPanel>
</Button>
版本 2 代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("This is the Ellipse");
// Shows this
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("This is the Button");
// Doesn't get to this point.
}
}
现在,奇怪的是,如果我从版本 n2 中删除 Ellipse
处理程序中的 MessageBox
代码,并放入任何其他内容,它将冒泡到Button
的处理程序并显示“这是按钮”消息。
这是什么奇怪的行为?为什么版本 1 冒泡并显示 BOTH MessageBox
es 但版本 2 只显示一个 MessageBox
并且除非我删除 MessageBox
否则不会冒泡代码?
When I have 2 MouseDown events, one for the Ellipse and one for the Stackpanel, whether I use MessageBox or not, it still bubbles up fine after showing the first MessageBox.
这是因为您没有将 Handled
属性 设置为 true
以停止进一步冒泡。
private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("This is the Ellipse");
e.Handled = true;
// Shows this
}
Why does Version 1 bubble up and show BOTH MessageBoxes but Version 2 only shows one MessageBox and doesn't bubble up unless I remove the MessageBox code?
This related answer 建议显示消息框有效地将焦点从 WPF window 移开,这会取消事件路由,而不管设置 Handled
属性。
The focus change to the message box cancels the mouse down event so it doesn't matter whether it is handled or not.
但是,我不同意这一点。根据我的观察和测试,此问题仅与模态 windows 有关(阻止您的 UI 进行交互)。您可以创建一个 WPF Window
并调用 ShowDialog
,这会导致相同的行为,而使用 Show
显示 window 或执行任何外部应用程序不会停止事件路由,即使焦点已从 WPF 应用程序移开。此外,正如您在代码中展示的那样,可以有任意数量的控件通过将模式 window 显示为 Button
的子级来处理 MouseDown
,这仍然有效,只是为了中断Click
Button
的事件处理程序。
事实上,调查事件Snoop,表明事件处理是相同的(左模态windows),事件没有被取消。该事件始终由 Button
处理,这是预期的,因为它是以这种方式实现的,但是如果之前显示了任何模态 window,则永远不会调用 Click
事件处理程序,尽管事件不是 Handled
(false
).
因此,我假设 Click
的事件处理在模态 windows 的场景中以某种方式被破坏。我没有在文档中找到任何关于此问题或预期的内容,只有 similar issue in the MSDN forums.
版本 1 XAML 代码:
<Button Padding="10" Background="Green" Width="500">
<StackPanel MouseDown="StackPanel_MouseDown" Background="Gray" Width="500" Height="300">
<Ellipse MouseDown="Ellipse_MouseDown" Width="100" Height="100" Fill="Red"></Ellipse>
</StackPanel>
</Button>
版本 1 代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("This is the Ellipse");
// Shows this MessageBox.
}
private void StackPanel_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("This is the StackPanel");
// Also shows this MessageBox.
}
}
当我有 2 个 MouseDown
事件时,一个用于 Ellipse
,一个用于 StackPanel
,无论我是否使用 MessageBox
,它仍然会冒泡在显示第一个 MessageBox
.
但是,如果我在 Button
上有 Click
事件,它将停止工作。
版本 2 XAML代码:
<Button Padding="10" Background="Green" Width="500" Click="Button_Click">
<StackPanel Background="Gray" Width="500" Height="300">
<Ellipse MouseDown="Ellipse_MouseDown" Width="100" Height="100" Fill="Red"></Ellipse>
</StackPanel>
</Button>
版本 2 代码隐藏:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("This is the Ellipse");
// Shows this
}
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("This is the Button");
// Doesn't get to this point.
}
}
现在,奇怪的是,如果我从版本 n2 中删除 Ellipse
处理程序中的 MessageBox
代码,并放入任何其他内容,它将冒泡到Button
的处理程序并显示“这是按钮”消息。
这是什么奇怪的行为?为什么版本 1 冒泡并显示 BOTH MessageBox
es 但版本 2 只显示一个 MessageBox
并且除非我删除 MessageBox
否则不会冒泡代码?
When I have 2 MouseDown events, one for the Ellipse and one for the Stackpanel, whether I use MessageBox or not, it still bubbles up fine after showing the first MessageBox.
这是因为您没有将 Handled
属性 设置为 true
以停止进一步冒泡。
private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("This is the Ellipse");
e.Handled = true;
// Shows this
}
Why does Version 1 bubble up and show BOTH MessageBoxes but Version 2 only shows one MessageBox and doesn't bubble up unless I remove the MessageBox code?
This related answer 建议显示消息框有效地将焦点从 WPF window 移开,这会取消事件路由,而不管设置 Handled
属性。
The focus change to the message box cancels the mouse down event so it doesn't matter whether it is handled or not.
但是,我不同意这一点。根据我的观察和测试,此问题仅与模态 windows 有关(阻止您的 UI 进行交互)。您可以创建一个 WPF Window
并调用 ShowDialog
,这会导致相同的行为,而使用 Show
显示 window 或执行任何外部应用程序不会停止事件路由,即使焦点已从 WPF 应用程序移开。此外,正如您在代码中展示的那样,可以有任意数量的控件通过将模式 window 显示为 Button
的子级来处理 MouseDown
,这仍然有效,只是为了中断Click
Button
的事件处理程序。
事实上,调查事件Snoop,表明事件处理是相同的(左模态windows),事件没有被取消。该事件始终由 Button
处理,这是预期的,因为它是以这种方式实现的,但是如果之前显示了任何模态 window,则永远不会调用 Click
事件处理程序,尽管事件不是 Handled
(false
).
因此,我假设 Click
的事件处理在模态 windows 的场景中以某种方式被破坏。我没有在文档中找到任何关于此问题或预期的内容,只有 similar issue in the MSDN forums.