Olja  Muravjova
Olja Muravjova

Reputation: 117

Access keys not working inside popup (WPF)

I have a simple popup in my WPF application. There is a button with access-key inside this popup.

The problem I have is that this button doesn't respond to Alt+access-key combination. Moreover pressing Alt doesn't make access key visible like it happens in ordinary window.

Is there any way to make controls inside popup respond to Alt+access-key combination?

P.S. I have no problem with navigation using Tab through this popup.

Sapmle code that I'm using

     <Grid>
        <Button Click="ButtonBase_OnClick" Content="_Open File"></Button>
        <Popup x:Name="Popup" StaysOpen="False">
            <Grid Background="White">
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Button Content="_Open File"/>
                <Button Grid.Row="1" Content="O_pen File"/>
                <CheckBox Grid.Row="2" Content="_Go"></CheckBox>
            </Grid>
        </Popup>
    </Grid>
    private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
    {
      Popup.IsOpen = true;
    }

I have also tried adding this as the first answer suggests

    private void Popup_OnOpened(object sender, EventArgs e)
    {
      var popup = sender as Popup;
      popup.Child.Focusable = true;
      Keyboard.Focus(popup.Child);
    }

I have also tried the idea from the first comment

    private void Popup_OnOpened(object sender, EventArgs e)
    {
      var popup = sender as Popup;
      FocusManager.SetIsFocusScope(popup, true);
    }

or instead of standart focus scope the one from suggested link codeproject.com/Articles/38507/Using-the-WPF-FocusScope

   EnhancedFocusScope.SetFocusOnActiveElementInScope(popup);

Setting focus scope helped a little bit, but I didn't manage to make it work exactly as I would like. Setting focus scope to true did help to use alt+key combination for checkboxes and label+textbox, but not for buttons. Although I could use Alt+access key combinations, I couldn't actually see them, because underscores didn't appear when I pressed Alt

Upvotes: 2

Views: 545

Answers (2)

sa.he
sa.he

Reputation: 1421

Once a button or a checkbox inside the popup is focused, the alt-shortcuts works.

<Button Click="ButtonBase_OnClick" Content="_Open File" />
<Popup x:Name="Popup">
    <StackPanel Background="White">
        <CheckBox x:Name="FirstCeckbox" Content="_Foo" />
        <CheckBox Content="_Bar" />
    </StackPanel>
</Popup>

Code behind:

private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
    Popup.IsOpen = !Popup.IsOpen;
    if (Popup.IsOpen)
        FirstCeckbox.Focus();  // Make sure to focus a Button or a Checkbox, not the Stackpanel or Grid etc.
}

Upvotes: 0

BionicCode
BionicCode

Reputation: 28988

Popup is not part of the visual tree. This means it has its own isolated focus scope. When a Popup is opened, the Popup.Child is hosted in a dedicated Window with its own detached visual tree. The Popup.Child therefore needs to explicitly receive keyboard focus before the access keys are available in the detached focus scope.

You can handle the Popup.Opened event, either in code-behind or using an attached behavior.
It's essential that the Popup.Child is focusable in order to receive keyboard focus.
Some classes like Panel and its subclasses have UIElement.Focusable set to false by default.

<StackPanel>
  <ToggleButton x:Name="ToggleButton" Content="Show Popup" />
  <Popup x:Name="Popup" 
        AllowsTransparency="True"  
        PlacementTarget="{Binding ElementName=ToggleButton}" 
        IsOpen="{Binding ElementName=ToggleButton, Path=IsChecked}" 
        Opened="Popup_OnOpened">
    <StackPanel>
      <Button Grid.Row="1" Content="O_pen File" />
      <CheckBox Grid.Row="2" Content="_Go" />
    </StackPanel>
  </Popup>
</StackPanel>

private void Popup_OnOpened(object sender, EventArgs e)
{
  var popup = sender as Popup;
  popup.Child.Focusable = true;
  Keyboard.Focus(popup.Child);
}

Upvotes: 1

Related Questions