Home > other >  How to disable Enter Key for a Button
How to disable Enter Key for a Button

Time:12-03

I have a button that has a command binded to it and also a key binding for F1 key. When the focus is on that button, the Enter key also triggers the command, which I do not want. I want the button to be triggered only for F1 and mouse click. How to disable this Enter key?

<Button Name="TestButton" Content="Run (F1)" Margin="10,4" Width="100" FontSize="16" Command="{Binding TestRunCommand}">
    <Button.Style>
        <Style TargetType="Button" BasedOn="{StaticResource ResourceKey=BlackButton}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsEnabled,ElementName=TestButton}" Value="True">
                    <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=TestButton}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

My key binding is as follows:

<UserControl.InputBindings>
    <KeyBinding Key="F1" Command="{Binding Path=TestViewModel.TestRunCommand}"/>
</UserControl.InputBindings>

When I remove the focus trigger, then the F1 key is also not working. So, I had this Setter property for F1 key to work.

CodePudding user response:

You can attach an event handler for the PreviewKeyDown event:

<Button Name="TestButton" Content="Run (F1)" Margin="10,4" Width="100" FontSize="16" Command="{Binding TestRunCommand}" PreviewKeyDown="OnPreviewKeyDown">

In the event handler, check for the Enter key and handle the event.

private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
   e.Handled = (e.Key == Key.Enter || e.Key == key.Return);
}

A slightly more creative variant would be to create an ICommand that does not do anything. It would be bound as KeyBinding to the Enter key, thus blocking the original command. I created a markup extension just for the ease of use.

public class IgnoreCommandExtension : MarkupExtension
{
   private static readonly IgnoreCommand IgnoreCommandInstance = new IgnoreCommand();

   private class IgnoreCommand : ICommand
   {
      public bool CanExecute(object parameter)
      {
         return true;
      }

      public void Execute(object parameter)
      {
      }

      public event EventHandler CanExecuteChanged;
   }

   public override object ProvideValue(IServiceProvider serviceProvider)
   {
      return IgnoreCommandInstance;
   }
}
<Button Name="TestButton" Content="Run (F1)" Margin="10,4" Width="100" FontSize="16" Command="{Binding TestRunCommand}">
    <Button.InputBindings>
       <KeyBinding Key="Enter" Command="{local:IgnoreCommand}"/>
       <KeyBinding Key="Return" Command="{local:IgnoreCommand}"/>
    </Button.InputBindings>
    <!-- ...other code. -->
</Button>

CodePudding user response:

Just remove Command="{Binding TestRunCommand}" from <Button ...> and the button won't do anything when being pressed.

Here's a minimal and complete example:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:DC/>
    </Window.DataContext>
    <Window.InputBindings>
        <KeyBinding Key="F1" Command="{Binding Path=F1Command}"/>
    </Window.InputBindings>
    <StackPanel>
        <Button Name="TestButton" Content="Run (F1)" Margin="10,4" Width="100" FontSize="16" 
Command="{Binding TestRunCommand}">
<!-- ^- remove this if you want it to do nothing -->
            <Button.Style>
                <Style TargetType="Button" >
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding IsEnabled,ElementName=TestButton}" Value="True">
                            <Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName=TestButton}"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
    </StackPanel>
</Window>

And the code behind:

public class DC
{
    public ICommand TestRunCommand
    {
        get { return new CommandHandler(() => MessageBox.Show("Enter / Space / Click"), () => true); }
    }

    public ICommand F1Command
    {
        get { return new CommandHandler(() => MessageBox.Show("F1"), () => true); }
    }
}

public class CommandHandler : ICommand
{
    private readonly Action _action;
    private readonly Func<bool> _canExecute;
    public CommandHandler(Action action, Func<bool> canExecute)
    {
        _action = action;
        _canExecute = canExecute;
    }
    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested  = value;
        remove => CommandManager.RequerySuggested -= value;
    }
    public bool CanExecute(object parameter) => _canExecute.Invoke();
    public void Execute(object parameter) => _action();
}
  • Related