WPF의 키보드 단축키


129

_대신 에 사용 하는 방법을 알고 &있지만 모든 Ctrl+ 유형 단축키를보고 있습니다.

Ctrl+ Z실행 취소, Ctrl+ S저장 등

WPF 응용 프로그램에서이를 구현하기위한 '표준'방법이 있습니까? 아니면 자신만의 롤을 사용하여 명령 / 제어에 연결합니까?

답변:


170

한 가지 방법은 바로 가기 키를 명령 자체에로 추가하는 것 InputGestures입니다. 명령은로 구현됩니다 RoutedCommands.

이를 통해 바로 가기 키가 컨트롤에 연결되어 있지 않아도 작동 할 수 있습니다. 메뉴 항목은 키보드 동작을 이해하므로 해당 명령을 메뉴 항목에 연결하면 메뉴 항목 텍스트에 바로 가기 키가 자동으로 표시됩니다.

  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) { ... }

4
명령을 메뉴 항목과 어떻게 연결합니까? 이 답변에 포함시켜야 할 가장 중요한 정보 일 것입니다.
Timwi

8
@Timwi : 위의 코드를 사용하여 기존 이벤트에 키보드 단축키를 추가했습니다. RoutedCommand cmndSettings = new RoutedCommand (); cmndSettings.InputGestures.Add (새 키 제스처 (Key.S, ModifierKeys.Control)); CommandBindings.Add (새 명령 바인딩 (cmndSettings, mnuSettings_Click));
itsho

1
itsho의 의견이 나를 위해이 작업을 수행했으며 위의 XML 코드를 작동시킬 수 없었습니다.
gosr

1
불행히도,이 접근 방식 Executed을 사용하면 명령의 코드는 일반적인 명령 (사용자 정의 ICommand구현) 을 사용하는 것과 달리보기 모델이 아닌 코드 숨김 (창 또는 사용자 제어의)으로 끝납니다 .
또는 매퍼


97

나는 이것이 WPF의 키 바인딩과 관련하여 정확히 찾고있는 것으로 나타났습니다.

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

블로그 게시물 MVVM CommandReference 및 KeyBinding 참조


아주 좋고 쉽습니다!
합병

1
"CreateCustomerCommand"가 무엇이며 어떻게 구현되는지 자세히 설명 하시겠습니까?
Vinz

복사 및 붙여 넣은 코드 스 니펫이 링크 된 블로그 게시물에 "결과는 예외가 될 것"으로 설명되어 있기 때문에 여전히 링크 전용 답변입니다. : P
Martin Schneider

작품은 여기에 놀랍습니다. 먼저 OP와 같이 버튼 내용의 키 앞에 "_"를 추가하려고 시도했지만 작동하지 않았습니다. 최악의 경우, ctrl-s 대신 "s"로 저장하는 인터페이스의 쓰기 가능한 개체에 초점을 맞출 수 없을 때 키 자체를 쳤을 때 활성화되었습니다.
Jay

14

이 코드를 사용해보십시오 ...

먼저 RoutedComand 객체를 만듭니다.

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

9

사용하려는 위치에 따라 다릅니다.

TextBoxBase파생 컨트롤은 이미 해당 바로 가기를 구현합니다. 사용자 정의 키보드 단축키를 사용하려면 명령 및 입력 제스처를 살펴보십시오. 다음은 Switch on the Code 의 작은 자습서입니다 . WPF 자습서-명령 바인딩 및 사용자 지정 명령


8
쓰레기 튜토리얼 – 무엇보다도 가장 중요한 것은 설명하지 않습니다. 미리 정의 된 20 개의 "공통"명령 중 하나가 아닌 명령을 사용하는 방법입니다.
Timwi

6

거의 참조 할 수없고 XAML을 전혀 건드릴 필요가없는 훨씬 간단한 방법이 있기 때문에 다른 사람을 위해이 답변을 문서화하십시오.

키보드 단축키를 연결하려면 Window 생성자에서 InputBindings 컬렉션에 새 KeyBinding을 추가하기 만하면됩니다. 명령으로 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();
        }
    }
}

5

나는 비슷한 문제가 있었고 @aliwa의 대답이 가장 도움이되고 가장 우아한 해결책이라는 것을 알았습니다. 그러나 특정 키 조합 Ctrl+가 필요했습니다 1. 불행히도 다음과 같은 오류가 발생했습니다.

'1'은 '키'의 값으로 사용할 수 없습니다. 숫자는 유효한 열거 값이 아닙니다.

약간의 추가 검색을 통해 @aliwa의 답변을 다음과 같이 수정했습니다.

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

나는 이것이 필요한 모든 조합에 잘 작동한다는 것을 알았습니다.


이것은 나를 위해 일한<UserControl.InputBindings> <KeyBinding Gesture="Enter" Command="{Binding someCommand}"/> </UserControl.InputBindings>
fs_tigre

3

VB.NET :

Public Shared SaveCommand_AltS As New RoutedCommand

로드 된 이벤트 내부 :

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

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

XAML이 필요하지 않습니다.


1

최고 답변은 정확하지만 개인적으로 첨부 속성을 사용하여 솔루션을 적용 할 수 있습니다 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 구현을 포함한 전체 샘플은 요점으로 제공됩니다. https://gist.github.com/shuebner20/c6a5191be23da549d5004ee56bcc352d

면책 조항 :이 코드는 어디서나 무료로 사용할 수 있습니다. 이 샘플은 사용량이 많은 샘플에는 적합하지 않습니다. 예를 들어, Command는 요소에 대한 강력한 참조를 보유하므로 제거 된 요소의 가비지 콜렉션이 없습니다.


-2

명령을 다음과 연결하는 방법 MenuItem:

<MenuItem Header="My command" Command="{x:Static local:MyWindow.MyCommand}"/>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.