在WPF中创建按键绑定

34

我需要为窗口创建输入绑定。

public class MainWindow : Window
{
    public MainWindow()
    {
        SomeCommand = ??? () => OnAction();
    }

    public ICommand SomeCommand { get; private set; }

    public void OnAction()
    {
        SomeControl.DoSomething();
    }
}

<Window>
    <Window.InputBindings>
        <KeyBinding Command="{Binding SomeCommand}" Key="F5"></KeyBinding>
    </Window.InputBindings>
</Window>

如果我使用一些CustomCommand : ICommand来初始化SomeCommand,它就不会触发。 SomeCommand的属性getter从未被调用。

5个回答

78

对于您的情况,最好使用MVVM模式。

XAML:

<Window>
    <Window.InputBindings>
        <KeyBinding Command="{Binding SomeCommand}" Key="F5"/>
    </Window.InputBindings>
</Window>

代码后台:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

在你的视图模型中:

public class MyViewModel
{
    private ICommand someCommand;
    public ICommand SomeCommand
    {
        get
        {
            return someCommand 
                ?? (someCommand = new ActionCommand(() =>
                {
                    MessageBox.Show("SomeCommand");
                }));
        }
    }
}

那么您将需要一个实现ICommand的类。

这是一个简单而有用的类。

public class ActionCommand : ICommand
{
    private readonly Action _action;

    public ActionCommand(Action action)
    {
        _action = action;
    }

    public void Execute(object parameter)
    {
        _action();
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public event EventHandler CanExecuteChanged;
}   

10
有没有一种快速简便的方法,在任何特定的按键组合(例如Ctrl+A)上运行一个名为void buttonPress() { MessageBox.Show("It works");}的方法?我已经在Google上搜索了20分钟,但找不到一个简单的示例来实现这一点。 - Matt
2
@MKII 不要忘记在 Mainwindow 方法中添加 DataContext = this; - keipa

21

对于键盘修饰键(组合键):

<KeyBinding Command="{Binding SaveCommand}" Modifiers="Control" Key="S"/>

6
这可能有点晚了,但这是最简单、最短的解决方案。
private void Window_KeyDown(object sender, KeyEventArgs e)
{
    if (Keyboard.Modifiers == ModifierKeys.Control && e.Key == Key.S)
    {
         // Call your method here
    }
}

<Window x:Class="Test.MainWindow" KeyDown="Window_KeyDown" >

它没有起作用。e.KeyLeftCtrlRightCtrl,因为只要按下修改键,就会触发它。 - Zaheer
这不是在实际事件被触发后检查按下的键盘修改键的当前状态吗?按下事件的状态应该在KeyEventArgs中,包括使用的修改键。这里的Keyboard看起来像一个(静态/本地)属性或静态类,我没有检查API的样子,但这可能是@Zaheer说这不起作用的原因。 - Paul-Sebastian Manole
换一下 if 语句中的参数怎么样?这样只有在 Key == Key.S 的情况下才会测试修饰符。 - dba

3
你需要创建一个实现了ICommand接口的自己的Command,并使用该Command的实例初始化SomeCommand。
现在,你需要将Window的DataContext设置为self,以使Command Binding工作。
public MainWindow()
{
    InitializeComponents();
    DataContext = this;
    SomeCommand = MyCommand() => OnAction();
}

否则,您将需要更新您的Binding,方法如下:

 <Window>
   <Window.InputBindings>
    <KeyBinding Command="{Binding SomeCommand, RelativeSource={RelativeSource Self}}" Key="F5"></KeyBinding>
   </Window.InputBindings>
 </Window>

1

这是我在项目中解决这个问题的方法:

<Window x:Class="MyNamespace.MyView"
    (...)
    xmlns:local="clr-namespace:MyNameSpace"
    (...)
    <Grid>
        <Grid.InputBindings>
            <KeyBinding Key="R" Command="{Binding ReportCommand, 
                RelativeSource={RelativeSource AncestorType=local:MyView}}" />
    (...)

ReportCommand 是在 MyView 中的一个 ICommand而不是 在 ViewModel 中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接