我的XAML有问题。我有一个菜单组件,我希望它也适用于快捷键。我有XAML代码,但不起作用:
<MenuItem Header="_New" Name="New" Click="New_Click" InputGestureText="Ctrl+N">
<MenuItem.InputBindings>
<KeyBinding Key="N" Modifiers="control"/>
</MenuItem.InputBindings>
</MenuItem>
解决方案是什么? New_Click事件有效,但是快捷键没有......
答案 0 :(得分:3)
使用InputGestureText
只会根据documentation向菜单项添加文字。您需要指定实际执行快捷方式时需要执行的操作。为此,您需要在ViewModel中创建一个ICommand,最好将该命令绑定到MenuItem.Command
因此,您生成的代码应如下所示:
<MenuItem Header="_New" Name="New" Command="{Binding NewCommand}" InputGestureText="Ctrl+N">
假设您的视图模型中有public ICommand NewCommand {...}
。
修改强>
执行此操作需要命令,因为这是WPF的工作方式。 WPF!= WinForms,在WinForms中你可以使用事件,在WPF中你想尝试使用ICommand
绑定。这已得到证实,并回答了关于为什么需要Command的问题:这是因为InputBinding实现了Command设计模式,所以你不会真正找到解决它的方法。
因此,实际上没有办法使用Click
事件处理程序而不是带有输入手势的Command
。如果您不打算使用Command(因为它们是在MVVM中使用),那么您将不得不在代码隐藏中添加ICommand,然后以编程方式设置绑定。
private RelayCommand qatRemoveItemCommand;
public ICommand RemoveItemCommand
{
get
{
if (this.RemoveItemCommand == null)
{
this.RemoveItemCommand = new RelayCommand(param => this.RemoveItem(), param => CanRemoveItem);
}
return this.RemoveItemCommand;
}
}
private void RemoveItem()
{
this.DeleteItem();
}
private bool CanRemoveItem
{
get
{
return true;
}
}
KeyBinding RemoveItemCmdKeyBinding = new KeyBinding(
this.RemoveItemCommand,
Key.N,
ModifierKeys.Control);
New.InputBindings.Add(OpenCmdKeyBinding);
<MenuItem Header="_New" Name="New" InputGestureText="Ctrl+N">
请注意,在卸载控件时可能需要删除或清除InputBindings,但我认为这将尽可能接近,更不用说我的原始答案答案是你的问题;您对其他信息的请求本身就是一个单独的问题。
另外,对从InputBinding实现继承的类进行一些研究,KeyBinding和MouseBinding
答案 1 :(得分:1)
可以在click上应用快捷方式。我们需要使用命令绑定来通过XAML实现此功能。 首先,您需要将命令绑定到MenuItem,然后将相同的命令绑定到keybinding。 以下是该工作代码:
<MenuItem Header="_New" Name="New" Command="{Binding NewCommand, Mode=TwoWay}" InputGestureText="Ctrl+N">
<MenuItem.InputBindings>
<KeyBinding Key="N" Modifiers="control" Command="{Binding NewCommand, Mode=TwoWay}"/>
</MenuItem.InputBindings>
</MenuItem>
NewCommand 将是ViewModel中的Icommand类型。 我正在提供C#代码,以便您理解命令绑定:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MyData();
}
}
public class MyData
{
public MyData()
{
this.NewCommand = new DelegateCommand(ExecuteShowMessage);
}
private void ExecuteShowMessage(object obj)
{
MessageBox.Show("Test");
}
public ICommand NewCommand { get; set; }
}
以上代码可根据您的要求使用。如果您对此有任何疑问,请与我们联系。 谢谢
答案 2 :(得分:1)
这是我的实用程序类:
using System;
using System.Windows;
using System.Windows.Input;
namespace NNN
{
/// <summary>This utility class translates ICommand calls to RoutedEventHandler calls</summary>
class c2e : ICommand
{
readonly RoutedEventHandler eh;
public c2e( RoutedEventHandler eh )
{
this.eh = eh;
}
public event EventHandler CanExecuteChanged;
bool ICommand.CanExecute( object parameter )
{
return true;
}
void ICommand.Execute( object parameter )
{
var a = new RoutedEventArgs();
this.eh( this, a );
}
}
static class Hotkey
{
/// <summary>Register event handler for hotkey</summary>
public static void registerHotkey( this Window wnd, Key key, ModifierKeys modifier, RoutedEventHandler handler )
{
ICommand cmd = new c2e( handler );
InputBinding ib = new InputBinding( cmd,new KeyGesture( key, modifier ) );
wnd.InputBindings.Add( ib );
}
}
}
用法示例:
public MainWindow()
{
InitializeComponent();
this.registerHotkey( Key.O, ModifierKeys.Control, menuOpen );
}
答案 3 :(得分:0)
由于上述解决方案都不适合我,因此我想在这里通过使用RoutedCommand
提出另一种解决方案。
XAML
<Window x:Class="CH02.ContextMenuDemo.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:CH02.ContextMenuDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.CommandBindings>
<CommandBinding Command="{x:Static local:MainWindow.MenuItemClickCommand}"
CanExecute="CanExecute"
Executed="OnMenuItemClicked"/>
</Window.CommandBindings>
<Grid>
<TextBlock Text="Right Click here to open Context Menu!"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TextWrapping="Wrap">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="My Menu Item"
Name="MyMenuItem"
Command="{x:Static local:MainWindow.MenuItemClickCommand}">
</MenuItem>
<Separator />
<MenuItem Header="Another Menu Item"
IsCheckable="True"
IsChecked="True"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</Grid>
</Window>
CS
public partial class MainWindow : Window
{
private static ICommand _clickCommand;
public static ICommand
MenuItemClickCommand => _clickCommand ??
(_clickCommand = new RoutedUICommand(
text: "Options",
name: "MenuItemClickCommand",
ownerType: typeof(MainWindow),
inputGestures: new InputGestureCollection(
inputGestures: new InputGesture[] {
new KeyGesture(Key.N, ModifierKeys.Control)
})));
public MainWindow()
{
InitializeComponent();
Focus();
}
private void OnMenuItemClicked(object sender, RoutedEventArgs e)
{
MessageBox.Show("Context menu item clicked!");
}
private void CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true; // or other logic
}
}