如何为运行时创建的通用按钮绑定热键并识别触发按键?
如何通过热键触发动态创建的按钮命令并获取触发按键信息
我来帮你搞定这两个需求:用热键(比如Ctrl+R)触发运行时生成的按钮,以及在TakeC方法里知道是哪个按键触发的命令。
一、让热键触发动态按钮的命令
你的按钮是从CButtons集合动态生成的,而且StyledButtonModel里的Name字段还存了热键(比如"Ctrl+R"),最合适的方式是为每个按钮动态创建对应的KeyBinding,这样每个热键就能精准触发对应按钮的命令,和点击按钮的效果完全一致。
你可以在UserControl的代码后台(或者ViewModel加载按钮数据的地方)加这段代码:
// 遍历所有按钮ViewModel foreach (var buttonVM in CButtons) { // 解析StyledButtonModel里的热键字符串(比如"Ctrl+R") if (Gesture.TryParse(buttonVM.Model.Name, out var inputGesture)) { // 创建KeyBinding,绑定到对应按钮的TakeCCommand var keyBinding = new KeyBinding { Command = buttonVM.TakeCCommand, CommandParameter = buttonVM, // 把按钮ViewModel传进去,和点击按钮时的参数一致 Gesture = inputGesture }; // 把这个KeyBinding添加到UserControl的输入绑定里 this.InputBindings.Add(keyBinding); } }
这样一来,当你按下对应热键时,就会直接触发该按钮的TakeCCommand,和点击按钮的逻辑完全打通。
二、在TakeC方法里获取触发的按键信息
默认的RelayCommand只传递你设置的CommandParameter,拿不到按键的触发信息,这里有两种简单的解决办法:
方法1:用支持事件参数的RelayCommand
很多MVVM框架的RelayCommand(比如Prism的DelegateCommand)都支持接收ExecutedRoutedEventArgs参数,这个参数里就包含了触发的按键信息。你可以修改命令的定义:
// 改成接收ExecutedRoutedEventArgs的RelayCommand TakeCCommand = new RelayCommand<ExecutedRoutedEventArgs>(TakeC); void TakeC(ExecutedRoutedEventArgs e) { // 获取触发的按键和修饰键(比如Ctrl、Shift) Key pressedKey = e.Key; ModifierKeys modifiers = e.KeyboardDevice.Modifiers; // 同时你还能拿到按钮ViewModel:e.Parameter就是我们之前绑定的buttonVM var buttonVM = e.Parameter as ButtonViewModel<StyledButtonModel>; }
方法2:把热键信息打包到CommandParameter里
如果你的RelayCommand只能接收自定义参数,那可以在创建KeyBinding时,把按钮ViewModel和热键信息一起传进去:
foreach (var buttonVM in CButtons) { if (Gesture.TryParse(buttonVM.Model.Name, out var inputGesture)) { // 用匿名对象打包两个信息 var commandParam = new { ButtonVM = buttonVM, HotKey = buttonVM.Model.Name }; var keyBinding = new KeyBinding { Command = buttonVM.TakeCCommand, CommandParameter = commandParam, Gesture = inputGesture }; this.InputBindings.Add(keyBinding); } }
然后修改TakeC方法:
void TakeC(object parameter) { // 解析参数 var param = parameter as dynamic; ButtonViewModel<StyledButtonModel> myClass = param.ButtonVM; string hotKey = param.HotKey; // 如果需要更细的按键信息,可以解析hotKey字符串 if (Gesture.TryParse(hotKey, out var gesture)) { var keyGesture = gesture as KeyGesture; if (keyGesture != null) { Key pressedKey = keyGesture.Key; ModifierKeys modifiers = keyGesture.Modifiers; // 这里就可以处理具体的按键信息了 } } }
额外提示:如果只需要单一热键触发
如果你只是想用Ctrl+R触发某个特定按钮,那可以直接修改XAML里的KeyBinding,把CommandParameter指向目标按钮的ViewModel,或者直接传递热键字符串:
<UserControl.InputBindings> <KeyBinding Command="{Binding TakeC, Source=self}" CommandParameter="Ctrl+R" Gesture="CTRL+R" /> </UserControl.InputBindings>
然后在TakeC里根据这个参数找到对应的按钮即可。
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

