Phím tắt trong WPF


129

Tôi biết về việc sử dụng _thay vì &, nhưng tôi đang xem tất cả các Ctrlphím tắt +.

Ctrl+ Zđể hoàn tác, Ctrl+ Sđể lưu, v.v.

Có cách 'tiêu chuẩn' nào để thực hiện những điều này trong các ứng dụng WPF không? Hoặc đó là một trường hợp cuộn của riêng bạn và nối chúng với bất kỳ lệnh / điều khiển nào?

Câu trả lời:


170

Một cách là thêm các phím tắt của bạn vào chính các lệnh đó InputGestures. Các lệnh được thực hiện như RoutedCommands.

Điều này cho phép các phím tắt hoạt động ngay cả khi chúng không được nối với bất kỳ điều khiển nào. Và vì các mục menu hiểu cử chỉ bàn phím, chúng sẽ tự động hiển thị phím tắt của bạn trong văn bản của các mục menu, nếu bạn nối lệnh đó với mục menu của bạn.

  1. Tạo thuộc tính tĩnh để giữ lệnh (tốt nhất là thuộc tính trong lớp tĩnh bạn tạo cho lệnh - nhưng đối với một ví dụ đơn giản, chỉ cần sử dụng thuộc tính tĩnh trong window.cs):

     public static RoutedCommand MyCommand = new RoutedCommand();
  2. Thêm (các) phím tắt cần gọi phương thức:

     MyCommand.InputGestures.Add(new KeyGesture(Key.S, ModifierKeys.Control));
  3. Tạo một ràng buộc lệnh trỏ đến phương thức của bạn để gọi thực thi. Đặt chúng trong các ràng buộc lệnh cho phần tử UI mà theo đó nó sẽ hoạt động (ví dụ: cửa sổ) và phương thức:

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

4
Làm cách nào để liên kết lệnh với một mục menu? Chắc chắn đó sẽ là thông tin quan trọng nhất để đưa vào câu trả lời này, nhưng nó bị thiếu.
Timwi

8
@Timwi: Tôi đã sử dụng mã ở trên theo cách này để thêm lối tắt bàn phím vào một sự kiện hiện có: RoutedCommand cmndSinstall = new RoutedCommand (); cmndSinstall.InputGestures.Add (KeyGesture mới (Key.S, ModifierKeys.Control)); CommandBindings.Add (CommandBinding mới (cmndSinstall, mnuSinstall_Click));
itho

1
Nhận xét của Itsho đã làm việc này cho tôi, không thể làm cho mã xml ở trên hoạt động.
gosr

1
Thật không may, với cách tiếp cận này, Executedmã cho lệnh sẽ kết thúc ở phía sau mã (của cửa sổ hoặc điều khiển người dùng) thay vì mô hình xem, trái ngược với sử dụng lệnh thông thường ( ICommandthực hiện tùy chỉnh ).
HOẶC Mapper


97

Tôi thấy đây chính xác là những gì tôi đang tìm kiếm liên quan đến ràng buộc chính trong WPF:

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

Xem bài đăng trên blog MVVM CommandReference và KeyBinding


Rất đẹp và dễ dàng!
sáp nhập

1
Bạn có muốn giải thích chi tiết về "CreatCustomerCommand" là gì và cách thức triển khai không?
Vinz

Đây vẫn chỉ là một câu trả lời liên kết vì đoạn mã sao chép và dán được mô tả với "Kết quả sẽ là một ngoại lệ" trên bài đăng blog được liên kết. : P
Martin Schneider

Công trình tuyệt vời ở đây. Trước tiên tôi đã thử thêm "_" vào trước khóa của nội dung nút, như OP, nhưng nó không hoạt động. Tệ nhất, nó đã kích hoạt khi tôi tự nhấn phím khi tôi không tập trung vào một đối tượng có thể ghi của giao diện .. như "s" để lưu, thay vì ctrl-s.
Jay

14

Hãy thử mã này ...

Đầu tiên tạo một đối tượng RoutedComand

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

9

Nó phụ thuộc vào nơi bạn muốn sử dụng những người.

TextBoxBaseđiều khiển được tạo ra đã thực hiện các phím tắt đó. Nếu bạn muốn sử dụng các phím tắt tùy chỉnh trên bàn phím, bạn nên xem qua Lệnh và cử chỉ Nhập liệu. Dưới đây là một hướng dẫn nhỏ từ Switch on the Code : WPF Tutorial - Command Bindings và Custom Commands


8
Thật là một hướng dẫn tào lao - không giải thích điều hoàn toàn quan trọng nhất, đó là làm thế nào để sử dụng một lệnh không xảy ra là một trong những lệnh được xác định trước của họ về 20 lệnh phổ biến.
Timwi

6

Ghi lại câu trả lời này cho người khác, vì có một cách đơn giản hơn nhiều để làm điều này hiếm khi được tham chiếu và hoàn toàn không cần phải chạm vào XAML.

Để liên kết một phím tắt, trong trình xây dựng Window, chỉ cần thêm KeyBinding mới vào bộ sưu tập InputBindings. Là lệnh, chuyển vào lớp lệnh tùy ý của bạn thực hiện ICommand. Đối với phương thức thực hiện, chỉ cần thực hiện bất kỳ logic nào bạn cần. Trong ví dụ của tôi dưới đây, lớp WindowCommand của tôi có một đại biểu mà nó sẽ thực thi bất cứ khi nào được gọi. Khi tôi xây dựng WindowCommand mới để chuyển qua với ràng buộc của mình, tôi chỉ cần chỉ ra trong trình khởi tạo của mình, phương thức mà tôi muốn WindowCommand thực thi.

Bạn có thể sử dụng mẫu này để đưa ra các phím tắt nhanh cho riêng mình.

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

Tạo một lớp WindowCommand đơn giản, có một ủy nhiệm thực thi để loại bỏ bất kỳ phương thức nào được đặt trên nó.

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

Tôi đã có một vấn đề tương tự và thấy câu trả lời của @ aliwa là giải pháp hữu ích và thanh lịch nhất; tuy nhiên, tôi cần một tổ hợp phím cụ thể, Ctrl+ 1. Thật không may, tôi đã nhận được lỗi sau:

'1' không thể được sử dụng làm giá trị cho 'Khóa'. Các số không phải là giá trị liệt kê hợp lệ.

Với một chút tìm kiếm, tôi đã sửa đổi câu trả lời của @ aliwa như sau:

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

Tôi thấy điều này hoạt động rất tốt cho bất kỳ sự kết hợp nào tôi cần.


Điều này làm việc cho tôi<UserControl.InputBindings> <KeyBinding Gesture="Enter" Command="{Binding someCommand}"/> </UserControl.InputBindings>
fs_tigre

3

VB.NET:

Public Shared SaveCommand_AltS As New RoutedCommand

Bên trong sự kiện được tải :

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

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

Không cần XAML.


1

Mặc dù các câu trả lời hàng đầu là chính xác, cá nhân tôi thích làm việc với các thuộc tính đính kèm để cho phép áp dụng giải pháp cho bất kỳ UIElement, đặc biệt là khi Windowkhông nhận thức được yếu tố cần tập trung. Theo kinh nghiệm của tôi, tôi thường thấy một bố cục của một số mô hình xem và điều khiển người dùng, trong đó cửa sổ thường không có gì khác là thùng chứa gốc.

Đoạn trích

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));
        }
    }
}

Với thuộc tính đính kèm này, bạn có thể xác định lối tắt tiêu điểm cho bất kỳ UIE bổ sung nào. Nó sẽ tự động đăng ký ràng buộc đầu vào tại cửa sổ có chứa phần tử.

Cách sử dụng (XAML)

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

Mã nguồn

Mẫu đầy đủ bao gồm triển khai FocusEuityCommand có sẵn dưới dạng ý chính: https://gist.github.com/shuebner20/c6a5191be23da549d5004ee56bcc352d

Tuyên bố miễn trừ trách nhiệm: Bạn có thể sử dụng mã này ở mọi nơi và miễn phí. Xin lưu ý rằng đây là mẫu không phù hợp để sử dụng nhiều. Ví dụ, không có bộ sưu tập rác của các phần tử bị xóa vì Lệnh sẽ giữ tham chiếu mạnh đến phần tử.


-2

Cách liên kết lệnh với a MenuItem:

<MenuItem Header="My command" Command="{x:Static local:MyWindow.MyCommand}"/>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.