If the intention is to allow users to enter a sequence of characters with controls such as comment / uncomment macros in visual studio, then you can do something like this (this is very rude, just give you an idea of how this will work)
Add a custom control that looks for keystrokes on it, and also contains a set of gestures to view.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Markup; namespace WpfApplication4 { [ContentProperty("Gestures")] public class KeyGestures : Control { public List<IKeyGesture> Gestures { get { return (List<IKeyGesture>)GetValue(GesturesProperty); } set { SetValue(GesturesProperty, value); } } public static readonly DependencyProperty GesturesProperty = DependencyProperty.Register("Gestures", typeof(List<IKeyGesture>), typeof(KeyGestures), new PropertyMetadata(null)); public List<string> CurrentSequence { get { return (List<string>)GetValue(CurrentSequenceProperty); } set { SetValue(CurrentSequenceProperty, value); } } public static readonly DependencyProperty CurrentSequenceProperty = DependencyProperty.Register("CurrentSequence", typeof(List<string>), typeof(KeyGestures), new PropertyMetadata(null)); public KeyGestures() { Gestures = new List<IKeyGesture>(); CurrentSequence = new List<string>(); } protected override void OnInitialized(EventArgs e) { var hostWindow = Window.GetWindow(this); if (hostWindow != null) { hostWindow.PreviewKeyDown += hostWinow_PreviewKeyDown; hostWindow.PreviewKeyUp += hostWinow_PreviewKeyUp; } base.OnInitialized(e); } bool IsAnyKeyPressed() { var allPossibleKeys = Enum.GetValues(typeof(Key)); bool results = false; foreach (var currentKey in allPossibleKeys) { Key key = (Key)currentKey; if (key != Key.None) if (Keyboard.IsKeyDown((Key)currentKey)) { results = true; break; } } return results; } void hostWinow_PreviewKeyUp(object sender, System.Windows.Input.KeyEventArgs e) { if (!IsAnyKeyPressed()) { CurrentSequence.Clear(); } } void hostWinow_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e) { if (e.SystemKey == Key.None) { if (!CurrentSequence.Contains(e.Key.ToString())) CurrentSequence.Add(e.Key.ToString()); } else if (!CurrentSequence.Contains(e.SystemKey.ToString())) CurrentSequence.Add(e.SystemKey.ToString()); foreach (var gesture in Gestures) if (gesture.IsComplete(this.CurrentSequence)) { if (gesture.Command != null && gesture.Command.CanExecute(gesture.CommandParameter)) gesture.Command.Execute(gesture.CommandParameter); System.Diagnostics.Debug.WriteLine("Completed gesture " + gesture); } } } public interface IKeyGesture { bool IsComplete(List<string> currentSequence); ICommand Command { get; } object CommandParameter { get; set; } } public class SequenceKeyGesture : DependencyObject, IKeyGesture { public string Sequence { get; set; } public char SplitChar { get; set; } public ICommand Command { get; set; } public object CommandParameter { get { return (object)GetValue(CommandParameterProperty); } set { SetValue(CommandParameterProperty, value); } } public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(SequenceKeyGesture), new PropertyMetadata(null)); public bool IsComplete(List<string> currentSequence) { string[] splitSequence = Sequence.Split(SplitChar); if (splitSequence.Length != currentSequence.Count) return false; if (splitSequence != null && splitSequence.Length > 0) for (int i = 0; i < splitSequence.Length; i++) if (splitSequence[i] != currentSequence[i]) return false; return true; } public SequenceKeyGesture() { SplitChar = '+'; } public override string ToString() { return Sequence; } } }
Then it can be used with the following xaml
<Window x:Class="WpfApplication4.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication4" Title="MainWindow" Height="350" Width="525"> <Grid> <local:KeyGestures> <local:SequenceKeyGesture Sequence="LeftAlt~S~C" SplitChar="~" Command="{Command binding here}" CommandParameter="Action1" /> <local:SequenceKeyGesture Sequence="LeftAlt+S+V" Command="{Command binding here" CommandParameter="Action2"/> </local:KeyGestures> </Grid> </Window>
There is Debug.WriteLine to show you when the gesture starts, if you want to test without setting up commands.
source share