WPF(XAML):快捷键事件

时间:2014-05-23 19:09:47

标签: wpf xaml events key shortcut

我的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事件有效,但是快捷键没有......

4 个答案:

答案 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实现继承的类进行一些研究,KeyBindingMouseBinding

答案 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
    }
}