WPF键盘焦点:菜单打开后失去焦点?

4
这似乎很容易,但实际上并没有按预期工作。在WPF 4.0中,我试图创建一个带有菜单栏的窗口,该菜单栏接受键盘快捷键...只是一个简单的窗口,在顶部有一个菜单栏和一些其他内容(在AvalonDock内部,这可能是问题的一部分)。
有一个限制:菜单栏和内容位于另一个用户控件中(我们称之为SadPanda,因为它让我感到沮丧),该用户控件是窗口的直接内容。逻辑层次结构看起来像这样(不是实际的XAML):
<Window>
  <UserControl x:Name="SadPanda" Focusable="True" FocusManager.IsFocusScope="True">
    <Grid>
      <MenuBar/>
      <AvalonDock:DockingManager>
        <PandaFood>
      </AvalonDock:DockingManager>
    </Grid>
  </UserControl>
</Window>

窗口的内容需要访问窗口的句柄,因此它在窗口加载后设置,如下所示:

window.Loaded += delegate { window.Content = new SadPanda(); };

菜单栏和快捷方式有被绑定在SadPanda上的路由命令,当键盘焦点丢失时,输入手势将不再起作用,因此会出现悲伤的熊猫。我添加了这个:
LostKeyboardFocus += (sender, e) => Debug.WriteLine("Lost focus to " + e.NewFocus);
GotKeyboardFocus += (sender, e) => Debug.WriteLine("Got focus from " + e.OldFocus);

…看起来焦点返回到窗口而不是SadPanda自身。如果我在窗口上设置Focusable="False",那么焦点就会变成null;控件甚至都不被考虑。我试过(由评论中的alpha-mouse建议):

window.GotKeyboardFocus += delegate { Keyboard.Focus(sadPanda); };

即使如此也无法正常工作--它会阻止菜单的打开(它们会闪现一下就消失了)或文本框永远无法获得焦点...我不确定为什么;它似乎是完美的解决方案。

基本上,我希望用户控件具有顶级键盘焦点,而不是窗口。最简单的实现方式是什么?

2个回答

3

我仍然不确定为什么这个方法有效,但是以下是我找到的解决方案:

  1. 窗口上设置 Focusable="False"FocusManager.IsFocusScope="False"
  2. 在控件上设置 Focusable="True"FocusManager.IsFocusScope="True"

三。使用以下代码:

PleasedPanda.LostKeyboardFocus += (sender, e) =>
{
    if(e.NewFocus == null)
    {
        Keyboard.Focus(PleasedPanda);
    }
}

我不确定为什么这个代码有效,而更明显的window.GotKeyboardFocus却无效,但这就是WPF。


1

在黑客的右侧。您可以处理Window.GotKeyboardFocus以立即聚焦SadPanda。但可能有更好的解决方案。


尝试过了,不起作用 ;-P。由于某种原因,这会导致菜单在打开后立即关闭。 - Robert Fraser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接