使 wpf 元素在失去焦点时隐藏

Make a wpf element hide when it loses focous

我有一个 WPF 菜单栏,它在程序启动时折叠起来,可以通过按 F10(如 Firefox)显示

<Menu x:Name="mainMenuBar" Height="20" Width="130" HorizontalAlignment="Left" DockPanel.Dock="Top" FocusManager.LostFocus="mainMenuBar_LostFocus">

我有一些代码,如果它失去焦点(即用户单击菜单栏和子菜单以外的其他地方),我会使用 FocusManager.LostFocus 属性.

private void showMenuBar(object sender, KeyEventArgs e)
{
    if(e.SystemKey == Key.F10)
    {
        mainMenuBar.Visibility = Visibility.Visible;
        mainMenuBar.Focus();
    }
}

private void mainMenuBar_LostFocus(object sender, RoutedEventArgs e)
{
    mainMenuBar.Visibility = Visibility.Collapsed;
}

当我点击菜单栏以外的地方时它不会折叠,但当我点击菜单栏时它会折叠。这种行为与我的预期相反,有人知道为什么会这样吗?

编辑:XAML代码

<Menu x:Name="mainMenuBar" Height="20" Width="130" HorizontalAlignment="Left" DockPanel.Dock="Top">
    <MenuItem Header="File">
        <Separator />
        <MenuItem Header="Exit" Click="menuFileExit_Click" ToolTip="Close Program" />
    </MenuItem>
    <MenuItem Header="Options">
        <MenuItem Header="Settings" Click="menuOptionsSettings_Click" />
    </MenuItem>
    <MenuItem Header="Help">
        <MenuItem Header="Read Me" Click="menuHelpReadMe_Click" />
        <MenuItem Header="Version History" Click="menuHelpVersionHistory_Click" />
        <MenuItem Header="About" Click="menuHelpAbout_Click" />
    </MenuItem>
</Menu>

我找到了获得所需行为的方法。 像您一样显示菜单,但即使不设置焦点。

protected override void OnKeyDown(KeyEventArgs e)
{
    if(e.SystemKey == Key.F10)
    {
        mainMenuBar.Visibility = Visibility.Visible;
    }
    base.OnKeyDown(e);
}

在您的菜单所在的 window 覆盖 OnPreviewMouseDown

protected override void OnPreviewMouseDown(MouseButtonEventArgs e)
{
    if (mainMenuBar.IsVisible && e.Source != mainMenuBar&& !IsMenuChildMouseDown(e.Source as FrameworkElement))
    {
        mainMenuBar.Visibility = Visibility.Collapsed;
    }
    base.OnPreviewMouseDown(e);
}

并创建方法 IsMenuChildMouseDown(FrameworkElement elem) 以检查鼠标是否在子菜单上按下。

    private bool IsMenuChildMouseDown(FrameworkElement elem)
    {
        if (elem == null)
            return false;

        DependencyObject parent = elem.Parent;

        if (parent == null)
            return false;
        else
        {
            if (parent == mainMenuBar)
                return true;

            return IsMenuChildMouseDown(parent as FrameworkElement);
        }
    }