我可以为WPF中的一系列键创建KeyBinding吗?

时间:2010-09-02 09:40:34

标签: wpf xaml keyboard-shortcuts binding key-bindings

是否可以在WPF中为一系列按键定义键绑定,例如Visual Studio中的快捷键,例如 Ctrl + R Ctrl + A 运行当前解决方案中的所有测试

据我所知,我只能使用该元素绑定单个键组合,如 Ctrl + S 。我可以使用此绑定序列,还是必须手动处理按键才能执行此操作?

3 个答案:

答案 0 :(得分:4)

您需要通过覆盖InputGesture方法来创建自己的Matches

类似的东西:

public class MultiInputGesture : InputGesture
{
    public MultiInputGesture()
    {
        Gestures = new InputGestureCollection();
    }

    public InputGestureCollection Gestures { get; private set; }

    private int _currentMatchIndex = 0;

    public override bool Matches(object targetElement, InputEventArgs inputEventArgs)
    {
        if (_currentMatchIndex < Gestures.Count)
        {
            if (Gestures[_currentMatchIndex].Matches(targetElement, inputEventArgs))
            {
                _currentMatchIndex++;
                return (_currentMatchIndex == Gestures.Count);
            }
        }
        _currentMatchIndex = 0;
        return false;
    }
}

它可能需要更多一点,比如忽略某些事件(例如KeyUp事件之间的KeyDown事件不应该重置_currentMatchIndex),但是你得到的图片......

答案 1 :(得分:0)

@ThomasLevesque的答案基本上是正确的,但不涉及重复键。 (请注意,按住Ctrl键将导致生成键重复事件。)如果用户在序列中间停顿,则超时也很有用。这是我正在使用的:

public class MultiKeyInputGesture : InputGesture {
    private const int MAX_PAUSE_MILLIS = 1500;

    private InputGestureCollection mGestures = new InputGestureCollection();

    private DateTime mLastWhen = DateTime.Now;
    private int mCheckIdx;

    public MultiKeyInputGesture(KeyGesture[] keys) {
        Debug.Assert(keys.Length > 0);

        // Grab a copy of the array contents.
        foreach (KeyGesture kg in keys) {
            mGestures.Add(kg);
        }
    }

    public override bool Matches(object targetElement, InputEventArgs inputEventArgs) {
        if (!(inputEventArgs is KeyEventArgs)) {
            // does this actually happen?
            return false;
        }

        DateTime now = DateTime.Now;
        if ((now - mLastWhen).TotalMilliseconds > MAX_PAUSE_MILLIS) {
            mCheckIdx = 0;
        }
        mLastWhen = now;

        if (((KeyEventArgs)inputEventArgs).IsRepeat) {
            // ignore key-repeat noise (especially from modifiers)
            return false;
        }

        if (!mGestures[mCheckIdx].Matches(null, inputEventArgs)) {
            mCheckIdx = 0;
            return false;
        }

        mCheckIdx++;
        if (mCheckIdx == mGestures.Count) {
            mCheckIdx = 0;
            inputEventArgs.Handled = true;
            return true;
        }

        return false;
    }
}

我通过在XAML中定义RoutedUICommand来使用它:

<Window.Resources>
    <RoutedUICommand x:Key="MyCommand" Text="My Command"/>
</Window.Resources>

通常从<Window.CommandBindings><MenuItem>引用。然后,在窗口构造函数中,我这样做:

RoutedUICommand ruic = (RoutedUICommand)FindResource("MyCommand");
ruic.InputGestures.Add(
    new MultiKeyInputGesture(new KeyGesture[] {
          new KeyGesture(Key.H, ModifierKeys.Control, "Ctrl+H"),
          new KeyGesture(Key.C, ModifierKeys.Control, "Ctrl+C")
    }) );

我发现this forum post有帮助。

除非您要尝试在链接的论坛帖子中尝试使用InputGestureText技巧,否则您需要为任何MenuItem添加一个明确的DisplayString

注意::按键手势处理程序“吃”完成手势的按键。如果您有多个处理程序,并且用户尝试连续使用两个多键序列(例如Ctrl + H,Ctrl + C,紧随其后的Ctrl + H,Ctrl + D),则第二个处理程序不会重置当按Ctrl + C时。相反,它将在第二个Ctrl + H到达时重置,并且会丢失该组合。实际行为取决于处理程序的调用顺序。我目前正在通过定义一个静态事件来处理此问题,该事件会在找到匹配项时触发,并向其订阅所有实例。

答案 2 :(得分:-1)

   <KeyBinding x:Name="mykeybinding" Gesture="CTRL+P" Key="E" 
                 Command="mycommand"/>

这似乎在我的结尾处伎俩,我必须按ctrl + P + E来执行“mycommand”

基于 http://msdn.microsoft.com/en-in/library/system.windows.input.keybinding.aspx