Search code examples
keyboardmauikey-bindingsenter

.NET MAUI Execute Button Command Upon <Enter> by User


I just wanted to know, is there any possibility to bind the keyboard input to executing a specific button command in .NET MAUI?

I've seen one can apparently use keyboard accelerators for the menu flyout on Windows and Mac, but is this also possible for any arbitrary keyboard input and button of the UI?


Solution

  • I've found a solution using SharpHook:

    I've created a "KeyboardService" which looks like the following:

    public class KeyboardService : IKeyboardService
    {
        private readonly IGlobalHook _hook;
        public IGlobalHook Hook { get =>  _hook; }
    
        public KeyboardService()
        {
            _hook = new TaskPoolGlobalHook();
            InitKeyboardHooks();
        }
    
        private async void InitKeyboardHooks()
        {
            await _hook.RunAsync();
        }
    }
    

    with the simple corresponding Interface for possible future mocking:

    public interface IKeyboardService
    {
        IGlobalHook Hook { get; }
    }
    

    Now upon navigating to the ViewModel using keyboard hooks I'm registering an event handler in ApplyQueryAttributes:

    public partial class TestViewModel : IQueryAttributable
    {
        private readonly IKeyboardService _keyboardService;
    
        public TestViewModel(
            IKeyboardService keyboardService)
        {
            _keyboardService = keyboardService;
        }
    
        public override void ApplyQueryAttributes(IDictionary<string, object> query)
        {
            _keyboardService.Hook.KeyPressed += keyboard_enter;
        }
    
        private void keyboard_enter(object? sender, KeyboardHookEventArgs e)
        {
            switch(e.Data.KeyCode)
            {
                case KeyCode.VcEnter:
                    OnKeyboardEnter();
                    break;
                default:
                    break;
            }
        }
    
        private void OnKeyboardEnter()
        {
            // ...
        }
    }
    

    Of course, upon leaving the page one needs to remember to unregister the event handler, since this SharpHook keyboard handler is globally used in the application, e.g. in another RelayCommand in the very same TestViewModel class:

    [RelayCommand]
    private async Task OnHomeViewAsync()
    {
        await NavigationService.NavigateToAsync("HomeView");
        _keyboardService.Hook.KeyPressed -= keyboard_enter;
    }
    

    This pattern can one repeat throughout the ViewModels in the application.

    However, I have not yet tried if one can effectively use keyboard combinations, such as Strg + Enter or Shift + Alt and so on.