Set keyboard interaction focus to a MenuFlyoutItem

235 views Asked by At

In a UWP app I have used MenuFlyoutItem to show drop down list. Here is xaml code

    <DropDownButton Style="{StaticResource DropDownButtonStyle1}" Name="MyDropDownButton" 
                Content="{Binding SelectedLanguage}" 
                RelativePanel.AlignRightWithPanel="True" 
                Margin="0,20,20,0" 
                FontSize="14">
        <DropDownButton.Flyout>
            <MenuFlyout x:Name="OptionMenu"
                        Placement="BottomEdgeAlignedRight">
            </MenuFlyout>
        </DropDownButton.Flyout>
    </DropDownButton>

Programmatically i am adding MenuFlyoutItem to MenuFlyout

foreach (Option option in _viewModel.Options)
{
    MenuFlyoutItem item = new MenuFlyoutItem();
    item.Text = option.text;
    LanguagesMenu.Items.Add(item);
}

Problem: When user use app with keyboard interaction the first MenuFlyoutItem is focused. I want different item to get focused (may be user previously selected item should get focused).

Example:

I have 3 option:

  1. Left
  2. Right
  3. Bottom

When user open MenuFlyout by keyboard Enter its by default focused first item -> Left. I want 2nd item -> Right to be focused.

How can i achieve this. I have read this Keyboard Interaction official doc but didn't find any idea.

1

There are 1 answers

7
Roy Li - MSFT On BEST ANSWER

You could directly use the Control.Focus(FocusState) Method to make the MenuFlyoutItem go to the focus state. I suggest you do this in the Flyout.Opened Event.

Based on your code, I made a simple demo and you might check it.

Xaml:

  <DropDownButton.Flyout>
            <MenuFlyout x:Name="OptionMenu"  Placement="BottomEdgeAlignedRight" Opened="OptionMenu_Opened">
            </MenuFlyout>
        </DropDownButton.Flyout>

Code behind:

private void OptionMenu_Opened(object sender, object e)
    {
        // let's say we need to set the seconed item as focused
        var list = OptionMenu.Items;
        MenuFlyoutItem item2 = list[1] as MenuFlyoutItem;

        item2.Focus(FocusState.Keyboard);
    }

Update:

Only make the item focused when the Enter key is pressed.

public Boolean IsKeyPressed = false;

  private void MainPage_Loaded(object sender, RoutedEventArgs e)
    {
        // same code 
        MenuFlyoutItem item = new MenuFlyoutItem();
        item.Text = "Left";

        MenuFlyoutItem item2 = new MenuFlyoutItem();
        item2.Text = "Right";

        MenuFlyoutItem item3 = new MenuFlyoutItem();
        item3.Text = "Bottom";

        OptionMenu.Items.Add(item);
        OptionMenu.Items.Add(item2);
        OptionMenu.Items.Add(item3);
        // handle the button keydown event.
        MyDropDownButton.PreviewKeyDown += MyDropDownButton_PreviewKeyDown;
    }

    private void MyDropDownButton_PreviewKeyDown(object sender, KeyRoutedEventArgs e)
    {
        //check if it is the Enter key
        if (e.Key == VirtualKey.Enter)
        {
            IsKeyPressed = true;
            Debug.WriteLine("Enter");
        }
        else 
        {
            return;
        }
    }

    private void OptionMenu_Opened(object sender, object e)
    {
        Debug.WriteLine("Open");

        if (IsKeyPressed) 
        {
            // let's say we need to set the seconed item as focused
            var list = OptionMenu.Items;
            MenuFlyoutItem item2 = list[1] as MenuFlyoutItem;

            item2.Focus(FocusState.Keyboard);
            //reset the flag  
            // You could do this in other places if you want.
            IsKeyPressed = false;
        }
       
    }