Caliburn Micro绑定快捷键

方式一: 

 <TextBox>
     <i:Interaction.Triggers>
         <i:KeyTrigger Key="H" Modifiers="Control">
             <cal:ActionMessage MethodName="EnterPressed" />
         </i:KeyTrigger>
     </i:Interaction.Triggers>
 </TextBox>

方式二: 绑定方式如下 需要在 Bootstrapper 的Configure添加如下代码即可

 <TextBox HorizontalAlignment="Left"
             Width="278"
             cal:Message.Attach="[Key Enter] = [EnterPressed]; [Gesture Ctrl+Enter] = [CtrlEnterPressed]; [Gesture Alt+Enter] = [AltEnterPressed]">
public class Bootstrapper : BootstrapperBase
    {
        public Bootstrapper()
        {
            Initialize();
        }

        protected override void Configure()
        {
            var defaultCreateTrigger = Parser.CreateTrigger;

            Parser.CreateTrigger = (target, triggerText) => 
            {
                if (triggerText == null)
                {
                    return defaultCreateTrigger(target, null);
                }

                var triggerDetail = triggerText
                    .Replace("[", string.Empty)
                    .Replace("]", string.Empty);

                var splits = triggerDetail.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);

                switch (splits[0])
                {
                    case "Key":
                        var key = (Key)Enum.Parse(typeof(Key), splits[1], true);
                        return new Microsoft.Xaml.Behaviors.Input.KeyTrigger() { Key = key };

                    case "Gesture":
                        var mkg = (MultiKeyGesture)(new MultiKeyGestureConverter()).ConvertFrom(splits[1]);
                        return new Microsoft.Xaml.Behaviors.Input.KeyTrigger { Modifiers = mkg.KeySequences[0].Modifiers, Key = mkg.KeySequences[0].Keys[0] };
                }

                return defaultCreateTrigger(target, triggerText);
            };
        }

        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            DisplayRootViewForAsync<ShellViewModel>();
        }
    }
 /// <summary>
    ///   Class used to store multi-key gesture data.
    /// </summary>
    public class KeySequence
    {
        /// <summary>
        ///   Gets the sequence of keys.
        /// </summary>
        /// <value> The sequence of keys. </value>
        public Key[] Keys { get; }

        /// <summary>
        ///   Gets the modifiers to be applied to the sequence.
        /// </summary>
        /// <value> The modifiers to be applied to the sequence. </value>
        public ModifierKeys Modifiers { get; }

        /// <summary>
        ///   Initializes a new instance of the <see cref="KeySequence" /> class.
        /// </summary>
        public KeySequence(ModifierKeys modifiers, params Key[] keys)
        {
            if (keys == null)
                throw new ArgumentNullException(nameof(keys));

            if (keys.Length < 1)
                throw new ArgumentException(@"At least 1 key should be provided", nameof(keys));

            Keys = new Key[keys.Length];
            keys.CopyTo(Keys, 0);
            Modifiers = modifiers;
        }

        /// <summary>
        ///   Returns a <see cref="string" /> that represents the current <see cref="object" /> .
        /// </summary>
        /// <returns> A <see cref="string" /> that represents the current <see cref="object" /> . </returns>
        public override string ToString()
        {
            var builder = new StringBuilder();

            if (Modifiers != ModifierKeys.None)
            {
                if ((Modifiers & ModifierKeys.Control) != ModifierKeys.None)
                    builder.Append("Ctrl+");
                if ((Modifiers & ModifierKeys.Alt) != ModifierKeys.None)
                    builder.Append("Alt+");
                if ((Modifiers & ModifierKeys.Shift) != ModifierKeys.None)
                    builder.Append("Shift+");
                if ((Modifiers & ModifierKeys.Windows) != ModifierKeys.None)
                    builder.Append("Windows+");
            }

            builder.Append(Keys[0]);

            for (var i = 1; i < Keys.Length; i++)
            {
                builder.Append("+" + Keys[i]);
            }

            return builder.ToString();
        }
    }
 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();

            AssociatedObject.KeyDown += OnAssociatedObjectKeyDown;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();

            AssociatedObject.KeyDown -= OnAssociatedObjectKeyDown;
        }

        private void OnAssociatedObjectKeyDown(object sender, KeyEventArgs e)
        {
            var key = (e.Key == Key.System) ? e.SystemKey : e.Key;
            if ((key == Key) && (Keyboard.Modifiers == GetActualModifiers(e.Key, Modifiers)))
            {
                InvokeActions(e);
            }
        }

        static ModifierKeys GetActualModifiers(Key key, ModifierKeys modifiers)
        {
            switch (key)
            {
                case Key.LeftCtrl:
                case Key.RightCtrl:
                    modifiers |= ModifierKeys.Control;
                    return modifiers;

                case Key.LeftAlt:
                case Key.RightAlt:
                    modifiers |= ModifierKeys.Alt;
                    return modifiers;

                case Key.LeftShift:
                case Key.RightShift:
                    modifiers |= ModifierKeys.Shift;
                    break;
            }

            return modifiers;
        }
    }
 /// <summary>
    ///   Class used to define a multi-key gesture.
    /// </summary>
    [TypeConverter(typeof(MultiKeyGestureConverter))]
    public class MultiKeyGesture : InputGesture
    {
        /// <summary>
        ///   The maximum delay between key presses.
        /// </summary>
        static readonly TimeSpan maximumDelay = TimeSpan.FromSeconds(1);

        /// <summary>
        ///   Determines whether the keyis define.
        /// </summary>
        /// <param name="key"> The key to check. </param>
        /// <returns> <c>True</c> if the key is defined as a gesture key; otherwise, <c>false</c> . </returns>
        static bool IsDefinedKey(Key key)
        {
            return ((key >= Key.None) && (key <= Key.OemClear));
        }

        /// <summary>
        ///   Gets the key sequences string.
        /// </summary>
        /// <param name="sequences"> The key sequences. </param>
        /// <returns> The string representing the key sequences. </returns>
        static string GetKeySequencesString(params KeySequence[] sequences)
        {
            if (sequences == null)
                throw new ArgumentNullException("sequences");
            if (sequences.Length == 0)
                throw new ArgumentException("At least one sequence must be specified.", "sequences");

            var builder = new StringBuilder();

            builder.Append(sequences[0].ToString());

            for (var i = 1; i < sequences.Length; i++)
                builder.Append(", " + sequences[i]);

            return builder.ToString();
        }

        /// <summary>
        ///   Determines whether the specified key is a modifier key.
        /// </summary>
        /// <param name="key"> The key. </param>
        /// <returns> <c>True</c> if the specified key is a modifier key; otherwise, <c>false</c> . </returns>
        static bool IsModifierKey(Key key)
        {
            return key == Key.LeftCtrl || key == Key.RightCtrl || key == Key.LeftShift || key == Key.RightShift || key == Key.LeftAlt || key == Key.RightAlt || key == Key.LWin || key == Key.RWin;
        }

        /// <summary>
        ///   The display string.
        /// </summary>
        readonly string displayString;

        /// <summary>
        ///   The key sequences composing the gesture.
        /// </summary>
        readonly KeySequence[] keySequences;

        /// <summary>
        ///   The index of the current gesture key.
        /// </summary>
        int currentKeyIndex;

        /// <summary>
        ///   The current sequence index.
        /// </summary>
        int currentSequenceIndex;

        /// <summary>
        ///   The last time a gesture key was pressed.
        /// </summary>
        DateTime lastKeyPress;

        /// <summary>
        ///   Gets the key sequences composing the gesture.
        /// </summary>
        /// <value> The key sequences composing the gesture. </value>
        public KeySequence[] KeySequences
        {
            get { return keySequences; }
        }

        /// <summary>
        ///   Gets the display string.
        /// </summary>
        /// <value> The display string. </value>
        public string DisplayString
        {
            get { return displayString; }
        }

        /// <summary>
        ///   Initializes a new instance of the <see cref="MultiKeyGesture" /> class.
        /// </summary>
        /// <param name="sequences"> The key sequences. </param>
        public MultiKeyGesture(params KeySequence[] sequences)
            : this(GetKeySequencesString(sequences), sequences) { }

        /// <summary>
        ///   Initializes a new instance of the <see cref="MultiKeyGesture" /> class.
        /// </summary>
        /// <param name="displayString"> The display string. </param>
        /// <param name="sequences"> The key sequences. </param>
        public MultiKeyGesture(string displayString, params KeySequence[] sequences)
        {
            if (sequences == null)
                throw new ArgumentNullException("sequences");
            if (sequences.Length == 0)
                throw new ArgumentException("At least one sequence must be specified.", "sequences");

            this.displayString = displayString;
            keySequences = new KeySequence[sequences.Length];
            sequences.CopyTo(keySequences, 0);
        }

        /// <summary>
        ///   Determines whether this <see cref="System.Windows.Input.KeyGesture" /> matches the input associated with the specified <see
        ///    cref="System.Windows.Input.InputEventArgs" /> object.
        /// </summary>
        /// <param name="targetElement"> The target. </param>
        /// <param name="inputEventArgs"> The input event data to compare this gesture to. </param>
        /// <returns> true if the event data matches this <see cref="System.Windows.Input.KeyGesture" /> ; otherwise, false. </returns>
        public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
        {
            var args = inputEventArgs as KeyEventArgs;

            if (args == null || args.IsRepeat)
                return false;

            var key = args.Key != Key.System ? args.Key : args.SystemKey;
            //Check if the key identifies a gesture key...
            if (!IsDefinedKey(key))
                return false;

            var currentSequence = keySequences[currentSequenceIndex];
            var currentKey = currentSequence.Keys[currentKeyIndex];

            //Check if the key is a modifier...
            if (IsModifierKey(key))
            {
                //If the pressed key is a modifier, ignore it for now, since it is tested afterwards...
                return false;
            }

            //Check if the current key press happened too late...
            if (currentSequenceIndex != 0 && ((DateTime.Now - lastKeyPress) > maximumDelay))
            {
                //The delay has expired, abort the match...
                ResetState();
#if DEBUG_MESSAGES
                System.Diagnostics.Debug.WriteLine("Maximum delay has elapsed", "[" + MultiKeyGestureConverter.Default.ConvertToString(this) + "]");
#endif
                return false;
            }

            //Check if current modifiers match required ones...
            if (currentSequence.Modifiers != args.KeyboardDevice.Modifiers)
            {
                //The modifiers are not the expected ones, abort the match...
                ResetState();
#if DEBUG_MESSAGES
                System.Diagnostics.Debug.WriteLine("Incorrect modifier " + args.KeyboardDevice.Modifiers + ", expecting " + currentSequence.Modifiers, "[" + MultiKeyGestureConverter.Default.ConvertToString(this) + "]");
#endif
                return false;
            }

            //Check if the current key is not correct...
            if (currentKey != key)
            {
                //The current key is not correct, abort the match...
                ResetState();
#if DEBUG_MESSAGES
                System.Diagnostics.Debug.WriteLine("Incorrect key " + key + ", expecting " + currentKey, "[" + MultiKeyGestureConverter.Default.ConvertToString(this) + "]");
#endif
                return false;
            }

            //Move on the index, pointing to the next key...
            currentKeyIndex++;

            //Check if the key is the last of the current sequence...
            if (currentKeyIndex == keySequences[currentSequenceIndex].Keys.Length)
            {
                //The key is the last of the current sequence, go to the next sequence...
                currentSequenceIndex++;
                currentKeyIndex = 0;
            }

            //Check if the sequence is the last one of the gesture...
            if (currentSequenceIndex != keySequences.Length)
            {
                //If the key is not the last one, get the current date time, handle the match event but do nothing...
                lastKeyPress = DateTime.Now;
                inputEventArgs.Handled = true;
#if DEBUG_MESSAGES
                System.Diagnostics.Debug.WriteLine("Waiting for " + (m_KeySequences.Length - m_CurrentSequenceIndex) + " sequences", "[" + MultiKeyGestureConverter.Default.ConvertToString(this) + "]");
#endif
                return false;
            }

            //The gesture has finished and was correct, complete the match operation...
            ResetState();
            inputEventArgs.Handled = true;
#if DEBUG_MESSAGES
            System.Diagnostics.Debug.WriteLine("Gesture completed " + MultiKeyGestureConverter.Default.ConvertToString(this), "[" + MultiKeyGestureConverter.Default.ConvertToString(this) + "]");
#endif
            return true;
        }

        /// <summary>
        ///   Resets the state of the gesture.
        /// </summary>
        void ResetState()
        {
            currentSequenceIndex = 0;
            currentKeyIndex = 0;
        }
    }
 /// <summary>
    ///   Class used to define a converter for the <see cref="MultiKeyGesture" /> class.
    /// </summary>
    /// <remarks>
    ///   At the moment it is able to convert strings like <c>Alt+K,R</c> in proper multi-key gestures.
    /// </remarks>
    public class MultiKeyGestureConverter : TypeConverter
    {
        /// <summary>
        ///   The default instance of the converter.
        /// </summary>
        public static readonly MultiKeyGestureConverter DefaultConverter = new MultiKeyGestureConverter();

        /// <summary>
        ///   The inner key converter.
        /// </summary>
        static readonly KeyConverter keyConverter = new KeyConverter();

        /// <summary>
        ///   The inner modifier key converter.
        /// </summary>
        static readonly ModifierKeysConverter modifierKeysConverter = new ModifierKeysConverter();

        /// <summary>
        ///   Tries to get the modifier equivalent to the specified string.
        /// </summary>
        /// <param name="str"> The string. </param>
        /// <param name="modifier"> The modifier. </param>
        /// <returns> <c>True</c> if a valid modifier was found; otherwise, <c>false</c> . </returns>
        static bool TryGetModifierKeys(string str, out ModifierKeys modifier)
        {
            switch (str.ToUpper())
            {
                case "CONTROL":
                case "CTRL":
                    modifier = ModifierKeys.Control;
                    return true;
                case "SHIFT":
                    modifier = ModifierKeys.Shift;
                    return true;
                case "ALT":
                    modifier = ModifierKeys.Alt;
                    return true;
                case "WINDOWS":
                case "WIN":
                    modifier = ModifierKeys.Windows;
                    return true;
                default:
                    modifier = ModifierKeys.None;
                    return false;
            }
        }

        /// <summary>
        ///   Returns whether this converter can convert an object of the given type to the type of this converter, using the specified context.
        /// </summary>
        /// <param name="context"> An <see cref="System.ComponentModel.ITypeDescriptorContext" /> that provides a format context. </param>
        /// <param name="sourceType"> A <see cref="System.Type" /> that represents the type you want to convert from. </param>
        /// <returns> true if this converter can perform the conversion; otherwise, false. </returns>
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }

        /// <summary>
        ///   Converts the given object to the type of this converter, using the specified context and culture information.
        /// </summary>
        /// <param name="context"> An <see cref="System.ComponentModel.ITypeDescriptorContext" /> that provides a format context. </param>
        /// <param name="culture"> The <see cref="System.Globalization.CultureInfo" /> to use as the current culture. </param>
        /// <param name="value"> The <see cref="object" /> to convert. </param>
        /// <returns> An <see cref="object" /> that represents the converted value. </returns>
        /// <exception cref="System.NotSupportedException">The conversion cannot be performed.</exception>
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            var str = (value as string);

            if (!string.IsNullOrEmpty(str))
            {
                var sequences = str.Split(',');
                string[] keyStrings;

                var keySequences = new List<KeySequence>();


                foreach (var sequence in sequences)
                {
                    var modifier = ModifierKeys.None;
                    var keys = new List<Key>();
                    keyStrings = sequence.Split('+');
                    var modifiersCount = 0;

                    ModifierKeys currentModifier;
                    string temp;
                    while ((temp = keyStrings[modifiersCount]) != null && TryGetModifierKeys(temp.Trim(), out currentModifier))
                    {
                        modifiersCount++;
                        modifier |= currentModifier;
                    }

                    for (var i = modifiersCount; i < keyStrings.Length; i++)
                    {
                        var keyString = keyStrings[i];
                        if (keyString != null)
                        {
                            var key = (Key)keyConverter.ConvertFrom(keyString.Trim());
                            keys.Add(key);
                        }
                    }

                    keySequences.Add(new KeySequence(modifier, keys.ToArray()));
                }

                return new MultiKeyGesture(str, keySequences.ToArray());
            }

            throw GetConvertFromException(value);
        }

        /// <summary>
        ///   Converts the given value object to the specified type, using the specified context and culture information.
        /// </summary>
        /// <param name="context"> An <see cref="System.ComponentModel.ITypeDescriptorContext" /> that provides a format context. </param>
        /// <param name="culture"> A <see cref="System.Globalization.CultureInfo" /> . If null is passed, the current culture is assumed. </param>
        /// <param name="value"> The <see cref="object" /> to convert. </param>
        /// <param name="destinationType"> The <see cref="System.Type" /> to convert the <paramref name="value" /> parameter to. </param>
        /// <returns> An <see cref="object" /> that represents the converted value. </returns>
        /// <exception cref="System.ArgumentNullException">The
        ///   <paramref name="destinationType" />
        ///   parameter is null.</exception>
        /// <exception cref="System.NotSupportedException">The conversion cannot be performed.</exception>
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                var gesture = value as MultiKeyGesture;

                if (gesture != null)
                {
                    var builder = new StringBuilder();

                    KeySequence sequence;

                    for (var i = 0; i < gesture.KeySequences.Length; i++)
                    {
                        if (i > 0)
                            builder.Append(", ");

                        sequence = gesture.KeySequences[i];
                        if (sequence.Modifiers != ModifierKeys.None)
                        {
                            builder.Append((string)modifierKeysConverter.ConvertTo(context, culture, sequence.Modifiers, destinationType));
                            builder.Append("+");
                        }

                        builder.Append((string)keyConverter.ConvertTo(context, culture, sequence.Keys[0], destinationType));

                        for (var j = 1; j < sequence.Keys.Length; j++)
                        {
                            builder.Append("+");
                            builder.Append((string)keyConverter.ConvertTo(context, culture, sequence.Keys[0], destinationType));
                        }
                    }

                    return builder.ToString();
                }
            }

            throw GetConvertToException(value, destinationType);
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值