【问题标题】:Ignore repetition in KeyBinding (holding the key - execute command just once)忽略 KeyBinding 中的重复(按住键 - 只执行一次命令)
【发布时间】:2012-10-10 10:05:39
【问题描述】:

我在我的 xaml 中使用 KeyBindings 声明了键盘快捷键。 我想忽略重复,因为其中很少有键持有。

我只找到了使用事件并检查“IsRepetition”的解决方案,这并不真正适合我的键绑定声明。

当然,我可以在命令定义本身中执行此操作,并测量最后一次执行之间的时间差,但这让我无法区分多次按下和 1 次按住。

什么是仅在第一次按下时执行并在按住键时忽略其余部分的最佳方法?

【问题讨论】:

    标签: c# wpf xaml mvvm keyboard-shortcuts


    【解决方案1】:

    您正在尝试更改按钮的行为。最好为此使用代码。 最简单的方法是像这样将预览事件附加到窗口:

    <Window 
           ...
              PreviewKeyDown="HandlePreviewKeyDown">
    

    然后在代码中这样处理:

        private void HandlePreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.IsRepeat)
            {
                e.Handled = true;
            }
        }
    

    遗憾的是,这将禁用任何重复行为,即使在表单托管的文本框中也是如此。这是个有趣的问题。如果我找到一种更优雅的方法,我会添加到答案中。

    编辑:

    好的,有两种方法可以定义键绑定。

        <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
    
    
        <Window.InputBindings>
            <KeyBinding x:Name="altD" Gesture="Alt+D" Command="{Binding ClickCommand}"/>
        </Window.InputBindings>
    
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
                <Button Content="_Click" Command="{Binding ClickCommand}" />
            <TextBox Grid.Row="1"/>
        </Grid>
    </Window>
    

    上面的按钮会产生一次点击,因为您通过下划线隐含地请求了 Alt-C 手势:_Click 内容。然后窗口有一个与 Alt+D 的显式键绑定。

    后面的代码现在应该适用于这两种情况,并且不应干扰常规重复:

    protected override void OnPreviewKeyDown(KeyEventArgs e)
        {
            base.OnPreviewKeyDown(e);
    
            if (e.IsRepeat)
            {
                if (((KeyGesture)altD.Gesture).Matches(this, e))
                {
                    e.Handled = true;
                }
                else if (e.Key == Key.System)
                {
                    string sysKey = e.SystemKey.ToString();
                    //We only care about a single character here: _{character}
                    if (sysKey.Length == 1 && AccessKeyManager.IsKeyRegistered(null, sysKey))
                    {
                        e.Handled = true;
                    }
                }
            }
        }
    

    【讨论】:

    • 谢谢。但是我只希望这种行为适用于少数命令,而不适用于所有键盘输入:(
    【解决方案2】:

    我会说,如果您创建一个非常简单的状态机,该状态机将对 KeyDown 事件的 KeyBinding 执行操作,并且会忽略所有其他输入,直到触发 KeyUp 事件以给 KeyBinding 一个“一次性”行为.

    http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keyup.aspx

    【讨论】:

    • 我没有看到将其轻松集成到现有标记中的方法,我试图避免处理命令。
    【解决方案3】:

    使用 keyUp 方法代替 KeyDown。

    【讨论】:

      猜你喜欢
      • 2016-01-28
      • 2012-08-04
      • 2023-03-12
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2018-01-23
      • 2013-05-10
      相关资源
      最近更新 更多