Created
August 31, 2011 12:30
-
-
Save serbrech/1183423 to your computer and use it in GitHub Desktop.
KeyGestureBehavior
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text.RegularExpressions; | |
using System.Windows; | |
using System.Windows.Input; | |
using PagePlanner.Windows.Controls.TriggerActions; | |
namespace PagePlanner.Windows.Controls.Behaviours.KeyGestures | |
{ | |
public class KeyGestureCommandTrigger : KeyTrigger | |
{ | |
public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached( | |
"Command", | |
typeof(ICommand), | |
typeof(KeyGestureCommandTrigger), | |
new PropertyMetadata(OnCommandChanged) | |
); | |
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.RegisterAttached( | |
"CommandParameter", | |
typeof(object), | |
typeof(KeyGestureCommandTrigger), | |
null | |
); | |
public static readonly DependencyProperty GestureProperty = DependencyProperty.RegisterAttached( | |
"Gesture", | |
typeof(string), | |
typeof(KeyGestureCommandTrigger), | |
new PropertyMetadata(OnGestureChanged) | |
); | |
private static Regex gestureRx = new Regex(@"^\w+(\s*\+\s*\w+)*$", RegexOptions.IgnoreCase); | |
private static Dictionary<string, ModifierKeys> modifierMappings = new Dictionary<string, ModifierKeys>() | |
{ | |
{ "ctrl", ModifierKeys.Control } | |
}; | |
private static Dictionary<string, Key> keyMappings = new Dictionary<string, Key>() | |
{ | |
{ "del", Key.Delete }, | |
{ "ins", Key.Insert }, | |
{ "esc", Key.Escape } | |
}; | |
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | |
{ | |
var command = (ICommand)e.NewValue; | |
var actions = (System.Windows.Interactivity.TriggerActionCollection)d.GetValue(ActionsProperty); | |
var commandAction = (CommandTriggerAction)actions.FirstOrDefault(a => (a is CommandTriggerAction) && ((CommandTriggerAction)a).Command == command); | |
if (commandAction == null) | |
{ | |
actions.Add(new CommandTriggerAction() | |
{ | |
Command = GetCommand(d), | |
CommandParameter = GetCommandParameter(d) | |
}); | |
} | |
} | |
/// <summary> | |
/// Here we are going to parse provided gesture into the set of modifier keys and the main key. | |
/// </summary> | |
private static void OnGestureChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) | |
{ | |
string gesture = (string)e.NewValue; | |
ModifierKeys modifierKeys = ModifierKeys.None; | |
Key key = Key.None; | |
ParseGesture(gesture, out modifierKeys, out key); | |
d.SetValue(ModifiersProperty, modifierKeys); | |
d.SetValue(KeyProperty, key); | |
} | |
/// <summary> | |
/// Parses string gesture into the set of modifier keys and the main key. | |
/// </summary> | |
/// <param name="gesture">String gesture representation.</param> | |
/// <param name="modifierKeys">Modifier keys retuen value.</param> | |
/// <param name="key">Key return value.</param> | |
public static void ParseGesture(string gesture, out ModifierKeys modifierKeys, out Key key) | |
{ | |
if (string.IsNullOrEmpty(gesture)) | |
throw new ArgumentException("Gesture can not be empty string or null"); | |
if (!gestureRx.IsMatch(gesture)) | |
throw new ArgumentException("Wrong gesture format, should be something like 'Ctrl+E' or 'Ctrl+Shift+D'", "gesture"); | |
modifierKeys = ModifierKeys.None; | |
key = Key.None; | |
var tokens = gesture.Split('+'); | |
for (int i = 0; i < tokens.Length; i++) | |
{ | |
var token = tokens[i].Trim().ToLower(); | |
// We have modifier keys at the beginning. | |
if (i < tokens.Length - 1) | |
{ | |
try | |
{ | |
ModifierKeys modifierKey = (modifierMappings.ContainsKey(token)) ? | |
modifierMappings[token] : (ModifierKeys)Enum.Parse(typeof(ModifierKeys), token, true); | |
modifierKeys |= modifierKey; | |
} | |
catch (ArgumentException) | |
{ | |
throw new FormatException(string.Format("Could not recognize {0} key", token)); | |
} | |
} | |
// This is the main key. | |
else | |
{ | |
try | |
{ | |
key = (keyMappings.ContainsKey(token)) ? | |
keyMappings[token] : (Key)Enum.Parse(typeof(Key), token, true); | |
} | |
catch (ArgumentException) | |
{ | |
throw new FormatException(string.Format("Could not recognize {0} key", token)); | |
} | |
} | |
} | |
} | |
public static ICommand GetCommand(DependencyObject d) | |
{ | |
return (ICommand)d.GetValue(CommandProperty); | |
} | |
public static object GetCommandParameter(DependencyObject d) | |
{ | |
return d.GetValue(CommandParameterProperty); | |
} | |
public static string GetGesture(DependencyObject d) | |
{ | |
return (string)d.GetValue(GestureProperty); | |
} | |
public static void SetCommand(DependencyObject d, ICommand command) | |
{ | |
d.SetValue(CommandProperty, command); | |
} | |
public static void SetCommandParameter(DependencyObject d, object o) | |
{ | |
d.SetValue(CommandParameterProperty, o); | |
} | |
public static void SetGesture(DependencyObject d, string gesture) | |
{ | |
d.SetValue(GestureProperty, gesture); | |
} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// <summary> | |
/// This is a similar KeyTrigger as the one in the Expression Library, | |
/// except that it attaches to the element where it is declared instead of | |
/// the Application Root. | |
/// </summary> | |
public class KeyTrigger : TriggerBase<UIElement> | |
{ | |
public static readonly DependencyProperty KeyProperty = | |
DependencyProperty.Register("Key", typeof(Key), typeof(KeyTrigger), null); | |
public static readonly DependencyProperty ModifiersProperty = | |
DependencyProperty.Register("Modifiers", typeof(ModifierKeys), typeof(KeyTrigger), null); | |
public Key Key | |
{ | |
get { return (Key)GetValue(KeyProperty); } | |
set { SetValue(KeyProperty, value); } | |
} | |
public ModifierKeys Modifiers | |
{ | |
get { return (ModifierKeys)GetValue(ModifiersProperty); } | |
set { SetValue(ModifiersProperty, value); } | |
} | |
protected override void OnAttached() | |
{ | |
base.OnAttached(); | |
this.AssociatedObject.KeyDown += AssociatedObject_KeyDown; | |
} | |
protected override void OnDetaching() | |
{ | |
base.OnDetaching(); | |
this.AssociatedObject.KeyDown -= AssociatedObject_KeyDown; | |
} | |
private void AssociatedObject_KeyDown(object sender, KeyEventArgs e) | |
{ | |
if ((e.Key == this.Key) && (Keyboard.Modifiers == GetActualModifiers(e.Key, this.Modifiers))) | |
{ | |
base.InvokeActions(e); | |
} | |
} | |
private static ModifierKeys GetActualModifiers(Key key, ModifierKeys modifiers) | |
{ | |
if (key == Key.Ctrl) | |
{ | |
modifiers |= ModifierKeys.Control; | |
return modifiers; | |
} | |
if (key == Key.Alt) | |
{ | |
modifiers |= ModifierKeys.Alt; | |
return modifiers; | |
} | |
if (key == Key.Shift) | |
{ | |
modifiers |= ModifierKeys.Shift; | |
} | |
return modifiers; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment