【问题标题】:How to disable Enter Key for a Button如何禁用按钮的 Enter 键
【发布时间】: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 属性起作用。

【问题讨论】:

    标签: c# wpf xaml user-interface binding


    【解决方案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">
    

    这行得通。

    【讨论】:

      猜你喜欢
      • 2021-06-30
      • 2021-10-28
      • 2015-07-31
      • 1970-01-01
      • 2017-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-06
      相关资源
      最近更新 更多