WPF 已知问题 Popup 吃掉 PreviewMouseDown 事件
2023-09-27 14:28:48 时间
在 WPF 中,使用 Popup 也许会看到 PreviewMouseDown 事件被吃掉
因为 PreviewMouseDown 是 RoutingStrategy.Direct 路由事件,不能在多个视觉树使用,在设置 Popup 点击界面 StaysOpen="False" 的逻辑就在下面代码
private void OnPreviewMouseButton(MouseButtonEventArgs e)
{
// We should only react to mouse buttons if we are in an auto close mode (where we have capture)
if (_cacheValid[(int)CacheBits.CaptureEngaged] && !StaysOpen)
{
Debug.Assert( Mouse.Captured == _popupRoot.Value, "_cacheValid[(int)CacheBits.CaptureEngaged] == true but Mouse.Captured != _popupRoot");
// If we got a mouse press/release and the mouse isn't on the popup (popup root), dismiss.
// When captured to subtree, source will be the captured element for events outside the popup.
if (_popupRoot.Value != null && e.OriginalSource == _popupRoot.Value)
{
// When we have capture we will get all mouse button up/down messages.
// We should close if the press was outside. The MouseButtonEventArgs don't tell whether we get this
// message because we have capture or if it was legit, so we have to do a hit test.
if (_popupRoot.Value.InputHitTest(e.GetPosition(_popupRoot.Value)) == null)
{
// The hit test didn't find any element; that means the click happened outside the popup.
SetCurrentValueInternal(IsOpenProperty, BooleanBoxes.FalseBox);
}
}
}
}
如果写一个 CheckBox 放在界面上,运行代码可以看到可以被打勾但是没有事件
<Grid>
<StackPanel>
<Button Margin="10,10,10,10" Content="Open Popup" Click="OpenPopup_OnClick"></Button>
<CheckBox PreviewMouseDown="UIElement_OnPreviewMouseDown"></CheckBox>
</StackPanel>
<Popup x:Name="Popup" StaysOpen="False">
<Grid Width="100" Height="100" Background="White">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="Popup"></TextBlock>
</Grid>
</Popup>
</Grid>
在 UIElement_OnPreviewMouseDown
添加输出内容,代码如下,可以看到,没有符合预期输出
private void UIElement_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Debug.WriteLine("PreviewMouseDown");
}
private void OpenPopup_OnClick(object sender, RoutedEventArgs e)
{
Popup.PlacementTarget = (UIElement) sender;
Popup.Placement = PlacementMode.Mouse;
Popup.IsOpen = true;
}
本文代码放在 github 欢迎访问
此问题已报告 WPF 官方,请看 Known issus: Popup with “StaysOpen=false” steals PreviewMouseDown event · Issue #2166 · dotnet/wpf
更多请看 dotnet 读 WPF 源代码 Popup 的 StaysOpen 为 false 将会吃掉其他窗口的首次激活
相关文章
- 一站式WPF--依赖属性(DependencyProperty)一
- WPF基础学习第二天(高级控件)
- WPF 因设置不期望的DataContext,导致的绑定异常
- WPF 自定义Command
- WPF 通过 GifBitmapDecoder 调用 WIC 解析 Gif 和进行动画播放的简单方法
- 2018-8-10-WPF-DrawingVisual
- 2019-10-21-WPF-多个-StylusPlugIn-的事件触发顺序
- 2019-5-13-WPF-从触摸消息转触摸事件
- 2019-10-18-WPF-解决-StylusPlugIn-点击穿透问题
- 2018-10-20-WPF-通过位处理合并图片
- 2018-11-19-WPF-使用-SharpDX-在-D3DImage-显示
- 2019-7-29-WPF-元素裁剪-Clip-属性
- WPF 使用 Edge 浏览器
- wpf textbox ctrl+enter事件