web-dev-qa-db-ja.com

WPFのキーボードショートカット

私は_の代わりに&を使用することを知っていますが、私はすべてを見ています Ctrl +ショートカットを入力します。

Ctrl+Z 元に戻すために、 Ctrl+S 保存などのために.

これらをWPFアプリケーションに実装するための「標準的な」方法はありますか?それとも、独自にロールして、コマンド/コントロールに接続する場合ですか?

120
Benjol

標準的な方法は、コマンドを作成してからショートカットキーをInputGesturesとして追加することだと理解しています。

これにより、ショートカットキーがコントロールに接続されていなくても機能します。また、メニュー項目はキーボードジェスチャを理解するため、コマンドをメニュー項目にフックすると、メニュー項目のテキストにショートカットキーが自動的に表示されます。

  1. コマンドを保持する静的属性を作成します(コマンド用に作成する静的クラスのプロパティとして作成することをお勧めします-しかし、単純な例では、window.csで静的属性を使用します)。

    public static RoutedCommand MyCommand = new RoutedCommand();
    
  2. メソッドを呼び出すショートカットキーを追加します。

    MyCommand.InputGestures.Add(new KeyGesture(Key.S, ModifierKeys.Control));
    
  3. 実行時に呼び出すメソッドを指すコマンドバインディングを作成します。これらが機能するUI要素(ウィンドウなど)とメソッドのコマンドバインディングにこれらを配置します。

    <Window.CommandBindings>
        <CommandBinding Command="{x:Static local:MyWindow.MyCommand}" Executed="MyCommandExecuted"/>
    </Window.CommandBindings>
    
    private void MyCommandExecuted(object sender, ExecutedRoutedEventArgs e) { ... }
    
162
Abby Fichtner

私はこれがまさにWPFのキーバインディングに関連して探していたものであることがわかりました:

<Window.InputBindings>
        <KeyBinding Modifiers="Control"
                    Key="N"
                    Command="{Binding CreateCustomerCommand}" />
</Window.InputBindings>

ブログ投稿をご覧くださいMVVM CommandReference and KeyBinding

87
oliwa

このコードを試してください...

最初にRoutedComandオブジェクトを作成します

  RoutedCommand newCmd = new RoutedCommand();
  newCmd.InputGestures.Add(new KeyGesture(Key.N, ModifierKeys.Control));
  CommandBindings.Add(new CommandBinding(newCmd, btnNew_Click));
12

それらをどこで使用したいかによります。

TextBoxBase派生コントロールは、これらのショートカットを既に実装しています。カスタムキーボードショートカットを使用する場合は、コマンドと入力ジェスチャーを確認してください。以下は、コードのスイッチからの小さなチュートリアルです。 WPFチュートリアル-コマンドバインディングとカスタムコマンド

9
Anvaka

他の人のためにこの回答を文書化します。これは、ほとんど参照されず、XAMLに触れる必要のない、はるかに簡単な方法があります。

キーボードショートカットをリンクするには、Windowコンストラクターで、新しいKeyBindingをInputBindingsコレクションに追加するだけです。コマンドとして、ICommandを実装する任意のコマンドクラスを渡します。 executeメソッドの場合、必要なロジックを実装するだけです。以下の例では、WindowCommandクラスは、呼び出されるたびに実行されるデリゲートを受け取ります。バインドで渡す新しいWindowCommandを構築するとき、WindowCommandに実行させるメソッドを初期化子で指定するだけです。

このパターンを使用して、独自のクイックキーボードショートカットを作成できます。

public YourWindow() //inside any WPF Window constructor
{
   ...
   //add this one statement to bind a new keyboard command shortcut
   InputBindings.Add(new KeyBinding( //add a new key-binding, and pass in your command object instance which contains the Execute method which WPF will execute
      new WindowCommand(this)
      {
         ExecuteDelegate = TogglePause //REPLACE TogglePause with your method delegate
      }, new KeyGesture(Key.P, ModifierKeys.Control)));
   ...
}

単純なWindowCommandクラスを作成します。このクラスは、実行デリゲートを使用して、設定されているメソッドを起動します。

public class WindowCommand : ICommand
{
    private MainWindow _window;

    //Set this delegate when you initialize a new object. This is the method the command will execute. You can also change this delegate type if you need to.
    public Action ExecuteDelegate { get; set; }

    //You don't have to add a parameter that takes a constructor. I've just added one in case I need access to the window directly.
    public WindowCommand(MainWindow window)
    {
        _window = window;
    }

    //always called before executing the command, mine just always returns true
    public bool CanExecute(object parameter)
    {
        return true; //mine always returns true, yours can use a new CanExecute delegate, or add custom logic to this method instead.
    }

    public event EventHandler CanExecuteChanged; //i'm not using this, but it's required by the interface

    //the important method that executes the actual command logic
    public void Execute(object parameter)
    {
        if (ExecuteDelegate != null)
        {
            ExecuteDelegate();
        }
        else
        {
            throw new InvalidOperationException();
        }
    }
}
4
Ayo I

私は同様の問題を抱えており、@ aliwaの答えが最も有用でエレガントなソリューションであることがわかりました。ただし、特定のキーの組み合わせが必要でした。 Ctrl + 1。残念ながら、次のエラーが発生しました。

「1」は「キー」の値として使用できません。数値は有効な列挙値ではありません。

さらに少し検索して、@ aliwaの次の答えを修正しました。

<Window.InputBindings>
    <KeyBinding Gesture="Ctrl+1" Command="{Binding MyCommand}"/>
</Window.InputBindings>

これは、私が必要とする任意の組み合わせでうまく機能することがわかりました。

3
Nik

VB.NET:

Public Shared SaveCommand_AltS As New RoutedCommand

loadedイベント内:

SaveCommand_AltS.InputGestures.Add(New KeyGesture(Key.S, ModifierKeys.Control))

Me.CommandBindings.Add(New CommandBinding(SaveCommand_AltS, AddressOf Me.save))

XAMLは必要ありません。

2
plaasmeisie

一番上の答えは正しいですが、私は個人的に、特にUIElementがフォーカスされるべき要素を認識していない場合に、Windowにソリューションを適用できるように添付プロパティを操作したいと思っています。私の経験では、いくつかのビューモデルとユーザーコントロールの構成をよく目にしますが、ウィンドウはルートコンテナーにすぎません。

スニペット

public sealed class AttachedProperties
{
    // Define the key gesture type converter
    [System.ComponentModel.TypeConverter(typeof(System.Windows.Input.KeyGestureConverter))]
    public static KeyGesture GetFocusShortcut(DependencyObject dependencyObject)
    {
        return (KeyGesture)dependencyObject?.GetValue(FocusShortcutProperty);
    }

    public static void SetFocusShortcut(DependencyObject dependencyObject, KeyGesture value)
    {
        dependencyObject?.SetValue(FocusShortcutProperty, value);
    }

    /// <summary>
    /// Enables window-wide focus shortcut for an <see cref="UIElement"/>.
    /// </summary>
    // Using a DependencyProperty as the backing store for FocusShortcut.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FocusShortcutProperty =
        DependencyProperty.RegisterAttached("FocusShortcut", typeof(KeyGesture), typeof(AttachedProperties), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, new PropertyChangedCallback(OnFocusShortcutChanged)));

    private static void OnFocusShortcutChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if (!(d is UIElement element) || e.NewValue == e.OldValue)
            return;

        var window = FindParentWindow(d);
        if (window == null)
            return;

        var gesture = GetFocusShortcut(d);
        if (gesture == null)
        {
            // Remove previous added input binding.
            for (int i = 0; i < window.InputBindings.Count; i++)
            {
                if (window.InputBindings[i].Gesture == e.OldValue && window.InputBindings[i].Command is FocusElementCommand)
                    window.InputBindings.RemoveAt(i--);
            }
        }
        else
        {
            // Add new input binding with the dedicated FocusElementCommand.
            // see: https://Gist.github.com/shuebner20/349d044ed5236a7f2568cb17f3ed713d
            var command = new FocusElementCommand(element);
            window.InputBindings.Add(new InputBinding(command, gesture));
        }
    }
}

この添付プロパティを使用すると、UIElementのフォーカスショートカットを定義できます。要素を含むウィンドウで入力バインディングを自動的に登録します。

使用法(XAML)

<TextBox x:Name="SearchTextBox"
         Text={Binding Path=SearchText}
         local:AttachedProperties.FocusShortcutKey="Ctrl+Q"/>

ソースコード

FocusElementCommand実装を含む完全なサンプルは、Gistとして入手できます。 https://Gist.github.com/shuebner20/c6a5191be23da549d5004ee56bcc352d

免責事項:このコードはどこでも無料で使用できます。これは、大量使用には適さないサンプルであることに注意してください。たとえば、コマンドは要素への強い参照を保持するため、削除された要素のガベージコレクションはありません。

1