سؤال

This seems really easy, but it's definitely not working as expected. In WPF 4.0, I'm trying to create a window with a menu bar that accepts keyboard shortcuts... Just a simple window, a menu bar at the top, and some other stuff (inside AvalonDock, which may be part of the issue).

There's one catch: the menu bar & content are in another user control (let's call it SadPanda, because it's making me a sad panda) that is the direct content of the window. The logical hierarchy looks something like this (not actual XAML):

<Window>
  <UserControl x:Name="SadPanda" Focusable="True" FocusManager.IsFocusScope="True">
    <Grid>
      <MenuBar/>
      <AvalonDock:DockingManager>
        <PandaFood>
      </AvalonDock:DockingManager>
    </Grid>
  </UserControl>
</Window>

The content of the window needs access to the window's Handle, so it's set after the window loads like this:

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

The menu bar & shortcuts have routed commands that are bound to SadPanda, and when the keyboard focus is lost, the input gestures no longer work, hence the sad panda. I added this:

LostKeyboardFocus += (sender, e) => Debug.WriteLine("Lost focus to " + e.NewFocus);
GotKeyboardFocus += (sender, e) => Debug.WriteLine("Got focus from " + e.OldFocus);

... and it seems that the focus is returning to the Window, rather than to SadPanda itself. If I set Focusable="False" on the window, then the focus goes to null; the control is never even considered. I tried (suggested by alpha-mouse in comments):

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

Even this doesn't work -- it prevents menus from opening (they flash open for a second, then disappear) or text boxes from ever getting focus... Not sure why; it seems like the perfect solution.

Basically, I want the user control to have top-level keyboard focus, not the window. What's the easiest way to achieve this?

هل كانت مفيدة؟

المحلول

I'm still not sure why this works, but here's the solution I found:

  1. Set Focusable="False" and FocusManager.IsFocusScope="False" on the window.
  2. Set Focusable="True" and FocusManager.IsFocusScope="True" on the control.

Three. Use the following:

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

I'm not sure why this works while the more obvious window.GotKeyboardFocus doesn't, but that's WPF for you.

نصائح أخرى

On the right of a hack. You can handle Window.GotKeyboardFocus to immediately focus SadPanda. But may be there are nicer solutions.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top