如何禁用按钮的 Enter 键

Posted

技术标签:

【中文标题】如何禁用按钮的 Enter 键【英文标题】:How to disable Enter Key for a Button 【发布时间】:2022-01-09 05:01:37 【问题描述】:

我有一个绑定了命令的按钮以及 F1 键的键绑定。当焦点位于该按钮上时, Enter 键也会触发我不想要的命令。我希望仅在 F1 和鼠标单击时触发按钮。如何禁用此 Enter 键?

<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>

我的按键绑定如下:

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

当我移除焦点触发器时,F1 键也不起作用。所以,我让 F1 键的这个 Setter 属性起作用。

【问题讨论】:

【参考方案1】:

您可以为PreviewKeyDown 事件附加事件处理程序:

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

在事件处理程序中,检查 Enter 键并处理事件。

private void OnPreviewKeyDown(object sender, KeyEventArgs e)

   e.Handled = (e.Key == Key.Enter || e.Key == key.Return);


一个更有创意的变体是创建一个不做任何事情的ICommand。它将作为KeyBinding 绑定到 Enter 键,从而阻止原始命令。我创建了一个标记扩展,只是为了方便使用。

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>

【讨论】:

添加了另一个使用键绑定而不是事件处理程序的变体。【参考方案2】:

只需从&lt;Button ...&gt; 中删除Command="Binding TestRunCommand",按钮被按下时不会做任何事情。

这是一个最小且完整的示例:

<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>

以及背后的代码:

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();

【讨论】:

删除该命令后,鼠标单击功能将不起作用。我希望在 2 种情况下触发按钮命令 - 鼠标单击和 F1 键。不使用 Enter。 好的...下次您可能希望保留原始要求而不更改问题。由于您不希望您的产品负责人在冲刺期间更改需求,因此我们不喜欢在这里更改问题。【参考方案3】:

我终于想出了一个简单的方法来通过添加KeyboardNavigation.AcceptsReturn="False"来阻止Enter Key。

<Button Name="TestButton" Content="Run (F1)" Margin="10,4" Width="100" FontSize="16" Command="Binding TestRunCommand" KeyboardNavigation.AcceptsReturn="False">

这行得通。

【讨论】:

以上是关于如何禁用按钮的 Enter 键的主要内容,如果未能解决你的问题,请参考以下文章

如何禁用我的 textarea 上的 ENTER 键?

如何在使用 Blazor <InputText> 时禁用 ENTER 键按下提交按钮

禁用iOS键盘中的输入按钮

JavaScript 禁用表单中的Enter键

仅在 _some 字段上通过 Enter 键禁用表单提交

在窗体中禁用Enter键