microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.35k stars 678 forks source link

MenuBar KeyboardAccelerators do not work if using Binding until Menu opened once #5091

Closed Marv51 closed 1 year ago

Marv51 commented 3 years ago

Describe the bug Trying to invoke a KeyboardAccelerator defined in a MenuBar does not work from launching the app until the MenuBar is opened by mouse pointer at least once. After that, the KeyboardAccelerator works reliably.

This only occurs if the MenuFlyoutItem is using a Command which is bound with a {Binding.

Steps to reproduce the bug

<MenuBar>
    <MenuBarItem Title="Edit">
        <MenuFlyoutItem Text="Testing" Command="{Binding TestCommand, Mode=OneWay}">
            <MenuFlyoutItem.KeyboardAccelerators>
                <KeyboardAccelerator Modifiers="Control" Key="T" />
            </MenuFlyoutItem.KeyboardAccelerators>
        </MenuFlyoutItem>
    </MenuBarItem>
</MenuBar>

After launch press Ctrl + T and notice how TestCommand is not invoked. Click on 'Edit' MenuBarItem once. Now everytime you press ctrl + t the command gets invoked.

Expected behavior TestCommand should be invoked if ctrl+t is pressed.

Version Info

NuGet package version:

WinUI 3 - Project Reunion 0.5: 0.5.7

Windows app type: UWP Win32
Yes
Windows 10 version Saw the problem?
Insider Build (xxxxx)
May 2021 Update (19043) Yes
October 2020 Update (19042)
May 2020 Update (19041)
November 2019 Update (18363)
May 2019 Update (18362)
October 2018 Update (17763)
April 2018 Update (17134)
Fall Creators Update (16299)
Creators Update (15063)
Device form factor Saw the problem?
Desktop yes
Xbox
Surface Hub
IoT

Additional context Minimal Repro project: App7.zip

ranjeshj commented 3 years ago

This is by design. The framework does not know that those exist until the menu is opened. Can you add an accelerator for the Edit item ?

Marv51 commented 3 years ago

I switched to using 'x:Bind' or using the Click event, which solves the problem. If this is by design, then the design is broken.

It took me so long to figure out why sometimes some of my KeyboardAccelerators are not working.

Is there a way to programmatically open a MenuBar? I was thinking of working around this by opening all Menus from code once to work around this but couldn't figure out how to do that.

Marv51 commented 3 years ago

Can you add an accelerator for the Edit item ?

That wouldn't work like any other app I've ever seen before.

Practical example: If I have a "search" entry in the menu and I want to show a popup for search in my app (like many apps do). Then I can set the keyboard accelerator on that entry to ctrl + f and my app invokes the search command anytime that keyboard combo is pressed.

Except on app launch if I use Binding, because this bug occurs.

Additionally, please keep in mind that KeyboardAccelerators are distinct from AccessKeys.

ranjeshj commented 3 years ago

@Marv51 Thanks for the info. @Austin-Lamb and @MikeHillberg as FYI. Does x:Bind make it work end to end or do you still need to open all the menus ?

There isn't a straightforward API to open the menu bar programmatically unfortunately.

Marv51 commented 3 years ago

x:Bind makes it work end to end with no opening of the menu needed.

Marv51 commented 2 years ago

Just to follow up on this, the issue persists for me on WinAppSDK 1.0.2. Let me know if any further information would be helpful in solving this issue.

ifgotmoney commented 2 years ago

Just to follow up on this, the issue persists for me on WinAppSDK 1.0.2. Let me know if any further information would be helpful in solving this issue.

@Marv51, hello, can you please show an example how you fix this with x:bind. thanks

emorell96 commented 2 years ago

This is still broken. But doing Command="{x:Bind viewModel.OpenFileCommand}" fixes the issue, where viewModel is defined in:

<MenuBar.DataContext>
        <vm:MenuBarViewModel x:Name="viewModel" />
    </MenuBar.DataContext>
Marv51 commented 1 year ago

Keep alive (re #8638)

ranjeshj commented 1 year ago

If this works with x:Bind, then that would be a good option since x:Bind provides better performance and debugging as well.