Wiem o używaniu _
zamiast &
, ale patrzę na wszystkie Ctrlskróty typu +.
Ctrl+ Zdo cofania, Ctrl+ Sdo zapisywania itp.
Czy istnieje „standardowy” sposób ich implementacji w aplikacjach WPF? A może jest to przypadek skręcenia własnego i połączenia go z jakimkolwiek dowództwem / kontrolą?
źródło
Executed
kod polecenia skończy się w kodzie (okna lub kontroli użytkownika), a nie w modelu widoku, w przeciwieństwie do zwykłego polecenia (ICommand
implementacja niestandardowa ).Okazało się, że jest to dokładnie to, czego szukałem w związku z powiązaniem klucza w WPF:
<Window.InputBindings> <KeyBinding Modifiers="Control" Key="N" Command="{Binding CreateCustomerCommand}" /> </Window.InputBindings>
Zobacz wpis w blogu MVVM CommandReference i KeyBinding
źródło
+
npModifiers="Control+Alt"
. Zobacz stackoverflow.com/q/4050066Spróbuj tego.
Najpierw utwórz obiekt RoutedCommand:
RoutedCommand newCmd = new RoutedCommand(); newCmd.InputGestures.Add(new KeyGesture(Key.N, ModifierKeys.Control)); CommandBindings.Add(new CommandBinding(newCmd, btnNew_Click));
źródło
To zależy od tego, gdzie chcesz ich użyć.
TextBoxBase
- kontrolki pochodne już implementują te skróty. Jeśli chcesz używać niestandardowych skrótów klawiaturowych, zapoznaj się z poleceniami i gestami wprowadzania. Oto mały samouczek z Switch on the Code : Samouczek WPF - Powiązania poleceń i polecenia niestandardoweźródło
Udokumentowanie tej odpowiedzi dla innych, ponieważ istnieje znacznie prostszy sposób na zrobienie tego, który jest rzadko przywoływany i w ogóle nie wymaga dotykania XAML.
Aby połączyć skrót klawiaturowy, w konstruktorze Window po prostu dodaj nowy KeyBinding do kolekcji InputBindings. Jako polecenie przekaż dowolną klasę poleceń, która implementuje ICommand. W przypadku metody wykonywania po prostu zaimplementuj dowolną logikę, której potrzebujesz. W poniższym przykładzie moja klasa WindowCommand przyjmuje delegata, który będzie wykonywany po każdym wywołaniu. Kiedy konstruuję nowe WindowCommand do przekazania z moim powiązaniem, po prostu wskazuję w moim inicjatorze, metodę, którą chcę, aby WindowCommand wykonał.
Możesz użyć tego wzorca, aby wymyślić własne szybkie skróty klawiaturowe.
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))); ... }
Utwórz prostą klasę WindowCommand, która pobiera delegata wykonania, aby odpalić dowolną ustawioną metodę.
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(); } } }
źródło
Miałem podobny problem i uznałem, że odpowiedź @ aliwa jest najbardziej pomocnym i najbardziej eleganckim rozwiązaniem; potrzebowałem jednak określonej kombinacji klawiszy Ctrl+ 1. Niestety otrzymałem następujący błąd:
Przy odrobinie dalszych poszukiwań zmodyfikowałem odpowiedź @ aliwa na następujące:
<Window.InputBindings> <KeyBinding Gesture="Ctrl+1" Command="{Binding MyCommand}"/> </Window.InputBindings>
Okazało się, że to działa świetnie w przypadku dowolnej kombinacji, której potrzebowałem.
źródło
<UserControl.InputBindings> <KeyBinding Gesture="Enter" Command="{Binding someCommand}"/> </UserControl.InputBindings>
VB.NET:
Public Shared SaveCommand_AltS As New RoutedCommand
Wewnątrz załadowanego zdarzenia:
SaveCommand_AltS.InputGestures.Add(New KeyGesture(Key.S, ModifierKeys.Control)) Me.CommandBindings.Add(New CommandBinding(SaveCommand_AltS, AddressOf Me.save))
Nie jest potrzebny kod XAML.
źródło
Chociaż najlepsze odpowiedzi są poprawne, osobiście lubię pracować z dołączonymi właściwościami, aby umożliwić zastosowanie rozwiązania do dowolnego
UIElement
, zwłaszcza gdyWindow
nie jest świadomy elementu, na którym należy się skupić. Z mojego doświadczenia wynika, że często widzę kompozycję kilku modeli widoku i kontrolek użytkownika, w których okno jest często niczym więcej niż kontenerem głównym.Skrawek
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)); } } }
Dzięki tej dołączonej właściwości możesz zdefiniować skrót fokusu dla dowolnego elementu UIElement. Automatycznie zarejestruje powiązanie wejściowe w oknie zawierającym element.
Użycie (XAML)
<TextBox x:Name="SearchTextBox" Text={Binding Path=SearchText} local:AttachedProperties.FocusShortcutKey="Ctrl+Q"/>
Kod źródłowy
Pełny przykład, w tym implementacja FocusElementCommand, jest dostępny jako gist: https://gist.github.com/shuebner20/c6a5191be23da549d5004ee56bcc352d
Zastrzeżenie: Możesz używać tego kodu wszędzie i bezpłatnie. Należy pamiętać, że jest to próbka, która nie nadaje się do intensywnego użytkowania. Na przykład nie ma wyrzucania elementów bezużytecznych, ponieważ Polecenie będzie przechowywać silne odwołanie do elementu.
źródło
Specjalny przypadek: Twój skrót nie jest uruchamiany, jeśli fokus znajduje się na elemencie, który „nie jest natywny”. Na przykład w moim przypadku skupienie się na WpfCurrencyTextbox nie spowoduje wywołania skrótów zdefiniowanych w Twoim XAML (zdefiniowanym jak w odpowiedzi oliwy).
Rozwiązałem ten problem, ustawiając mój skrót jako globalny za pomocą pakietu NHotkey.
Krótko mówiąc, w przypadku XAML wszystko, co musisz zrobić, to wymienić
<KeyBinding Gesture="Ctrl+Alt+Add" Command="{Binding IncrementCommand}" />
przez
<KeyBinding Gesture="Ctrl+Alt+Add" Command="{Binding IncrementCommand}" HotkeyManager.RegisterGlobalHotkey="True" />
Odpowiedź została również wysłana do: Jak mogę zarejestrować globalny skrót klawiszowy, aby powiedzieć CTRL + SHIFT + (LETTER) przy użyciu WPF i .NET 3.5?
źródło
Jak skojarzyć polecenie z
MenuItem
:<MenuItem Header="My command" Command="{x:Static local:MyWindow.MyCommand}"/>
źródło