在WPF中,InputBindings
用于将输入(如键盘按键、鼠标操作)与命令(ICommand
)关联,实现输入触发命令的功能。它适用于各种控件(如 Window
、Button
、UserControl
等),是MVVM模式中处理输入的常用方式。
一、InputBindings
核心概念
- 组成 :包含两种常用绑定类型
KeyBinding
:键盘按键与命令绑定(最常用)MouseBinding
:鼠标操作(如单击、滚轮)与命令绑定
- 关联对象 :需绑定到实现
ICommand
接口的命令(如RelayCommand
、DelegateCommand
等) - 使用场景:快捷键、鼠标手势触发命令(如Ctrl+S保存、鼠标中键点击刷新等)
二、基础案例:在Window中使用KeyBinding
1. 准备命令(以RelayCommand为例)
首先定义一个简易的 RelayCommand
(实现 ICommand
),用于绑定:
csharp
using System;
using System.Windows.Input;
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter) => _canExecute?.Invoke(parameter) ?? true;
public void Execute(object parameter) => _execute.Invoke(parameter);
public event EventHandler CanExecuteChanged;
}
2. ViewModel中定义命令和处理方法
csharp
public class MainViewModel
{
// 保存命令
public ICommand SaveCommand { get; }
// 撤销命令
public ICommand UndoCommand { get; }
public MainViewModel()
{
// 初始化命令:执行保存操作
SaveCommand = new RelayCommand(_ => Save());
// 初始化命令:执行撤销操作(带参数)
UndoCommand = new RelayCommand(param => Undo(param?.ToString()));
}
private void Save()
{
// 保存逻辑(如写入文件)
Console.WriteLine("文件已保存");
}
private void Undo(string step)
{
// 撤销逻辑
Console.WriteLine($"撤销 {step ?? "1步"}");
}
}
3. XAML中绑定InputBindings
在 Window
的 InputBindings
中定义键盘快捷键:
xml
<Window x:Class="InputBindingsDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InputBindingsDemo"
Title="InputBindings示例" Height="300" Width="400">
<!-- 绑定ViewModel -->
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<!-- 定义输入绑定 -->
<Window.InputBindings>
<!-- Ctrl+S 触发保存命令 -->
<KeyBinding
Gesture="Ctrl+S"
Command="{Binding SaveCommand}" />
<!-- Ctrl+Z 触发撤销命令(带参数) -->
<KeyBinding
Key="Z"
Modifiers="Control"
Command="{Binding UndoCommand}"
CommandParameter="1步" />
</Window.InputBindings>
<Grid>
<TextBlock Text="按Ctrl+S保存,按Ctrl+Z撤销" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Window>
效果
- 按下
Ctrl+S
:触发Save()
方法,控制台输出"文件已保存" - 按下
Ctrl+Z
:触发Undo()
方法,控制台输出"撤销 1步"
三、进阶案例:MouseBinding与控件级绑定
1. 鼠标手势绑定(如鼠标中键点击触发命令)
在 UserControl
中使用 MouseBinding
:
xml
<UserControl x:Class="InputBindingsDemo.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InputBindingsDemo">
<UserControl.InputBindings>
<!-- 鼠标中键点击触发刷新命令 -->
<MouseBinding
MouseAction="MiddleClick" <!-- 鼠标中键点击 -->
Command="{Binding RefreshCommand}" />
<!-- 鼠标滚轮向上滚动触发放大命令 -->
<MouseBinding
MouseAction="WheelClick" <!-- 滚轮操作 -->
Gesture="Control+WheelUp" <!-- 按住Ctrl+滚轮向上 -->
Command="{Binding ZoomInCommand}" />
</UserControl.InputBindings>
<Grid>
<TextBlock Text="鼠标中键点击刷新,Ctrl+滚轮向上放大" />
</Grid>
</UserControl>
对应的ViewModel命令:
csharp
public class MyUserControlViewModel
{
public ICommand RefreshCommand { get; }
public ICommand ZoomInCommand { get; }
public MyUserControlViewModel()
{
RefreshCommand = new RelayCommand(_ => Console.WriteLine("刷新内容"));
ZoomInCommand = new RelayCommand(_ => Console.WriteLine("放大视图"));
}
}
2. 控件级绑定(如Button的快捷键)
为单个控件(如 Button
)绑定快捷键,仅当该控件获得焦点时生效:
xml
<Button Content="删除" Width="100" Height="30">
<Button.InputBindings>
<!-- 当Button获得焦点时,按Delete键触发删除命令 -->
<KeyBinding
Key="Delete"
Command="{Binding DeleteCommand}" />
</Button.InputBindings>
</Button>
四、高级用法:动态绑定与命令参数
1. 动态修改快捷键(代码-behind)
在后台代码中动态添加/移除 InputBinding
:
csharp
// 动态添加一个Ctrl+D的复制命令
var copyBinding = new KeyBinding(
viewModel.CopyCommand,
Key.D,
ModifierKeys.Control);
this.InputBindings.Add(copyBinding);
// 移除指定绑定
this.InputBindings.Remove(copyBinding);
2. 带动态参数的绑定
通过 CommandParameter
传递动态值(如绑定到控件的属性):
xml
<KeyBinding
Key="F5"
Command="{Binding SearchCommand}"
CommandParameter="{Binding Text, ElementName=searchTextBox}" />
<!-- 对应的文本框 -->
<TextBox x:Name="searchTextBox" />
ViewModel中接收参数:
csharp
SearchCommand = new RelayCommand(param =>
{
var keyword = param as string;
Console.WriteLine($"搜索关键词:{keyword}");
});
五、注意事项
-
快捷键冲突:避免与系统或其他应用快捷键冲突(如Ctrl+C、Ctrl+V)。
-
焦点问题 :
- 控件级
InputBindings
需控件获得焦点才生效。 - 窗口级
InputBindings
全局生效(无论焦点在哪)。
- 控件级
-
命令状态 :通过
CanExecute
控制命令是否可用(如保存命令在无修改时禁用):csharp// 示例:只有当有内容时才可保存 SaveCommand = new RelayCommand( _ => Save(), _ => HasContent // HasContent为ViewModel中的布尔属性 );
六、总结
InputBindings
是WPF中处理输入与命令关联的强大工具,核心用法可归纳为:
- 定义实现
ICommand
的命令(如RelayCommand
)。 - 在XAML或代码中通过
KeyBinding
/MouseBinding
关联输入与命令。 - 结合MVVM模式,将命令绑定到ViewModel的方法,实现业务逻辑与UI分离。
通过上述案例,可以灵活处理各种快捷键和鼠标操作场景,提升应用的交互性。