0

首先,这是我的代码:

<Window ...>
<Window.Resources>

</Window.Resources>
<Window.InputBindings>
    <KeyBinding Key="Space" Command="{Binding KeyboardCommand}" CommandParameter="Space"/>
    <KeyBinding Key="OemPeriod" Command="{Binding KeyboardCommand}" CommandParameter="Blank"/>
    <KeyBinding Key="D0" Command="{Binding KeyboardCommand}" CommandParameter="Rest"/>
    <KeyBinding Key="D1" Command="{Binding KeyboardCommand}" CommandParameter="N1"/>
    <KeyBinding Key="D2" Command="{Binding KeyboardCommand}" CommandParameter="N2"/>
    <KeyBinding Key="D3" Command="{Binding KeyboardCommand}" CommandParameter="N3"/>
    <KeyBinding Key="D4" Command="{Binding KeyboardCommand}" CommandParameter="N4"/>
    <KeyBinding Key="D5" Command="{Binding KeyboardCommand}" CommandParameter="N5"/>
    <KeyBinding Key="D6" Command="{Binding KeyboardCommand}" CommandParameter="N6"/>
    <KeyBinding Key="D7" Command="{Binding KeyboardCommand}" CommandParameter="N7"/>

    <KeyBinding Modifiers="Control" Key="Space" Command="{Binding KeyboardCommand}" CommandParameter="Space"/>
    <KeyBinding Modifiers="Control" Key="OemPeriod" Command="{Binding KeyboardCommand}" CommandParameter="Blank"/>
    <KeyBinding Modifiers="Control" Key="D0" Command="{Binding KeyboardCommand}" CommandParameter="Rest"/>
    <KeyBinding Modifiers="Control" Key="D1" Command="{Binding KeyboardCommand}" CommandParameter="N1"/>
    <KeyBinding Modifiers="Control" Key="D2" Command="{Binding KeyboardCommand}" CommandParameter="N2"/>
    <KeyBinding Modifiers="Control" Key="D3" Command="{Binding KeyboardCommand}" CommandParameter="N3"/>
    <KeyBinding Modifiers="Control" Key="D4" Command="{Binding KeyboardCommand}" CommandParameter="N4"/>
    <KeyBinding Modifiers="Control" Key="D5" Command="{Binding KeyboardCommand}" CommandParameter="N5"/>
    <KeyBinding Modifiers="Control" Key="D6" Command="{Binding KeyboardCommand}" CommandParameter="N6"/>
    <KeyBinding Modifiers="Control" Key="D7" Command="{Binding KeyboardCommand}" CommandParameter="N7"/>

    ...
</Window.InputBindings>
<Grid>
    ...
</Grid>

这些代码没有错误,所以它工作得很好。但是,如果我的应用程序InputBindings 很多InputBindings.

那么,是否可以(以任何方式)简化/缩短它们?那是因为我的应用会需要很多InputBindings/的修饰符组合,感觉一个一个输入会显得“不整齐”。米KeyBinding

或者也许这是唯一的方法(使用 MVVM)?

请澄清任何需要的东西:D


以防万一,这些是 Command 和 ViewModel 类中的相关方法:

public void Execute(object parameter)
{
    Notes note;
    if (Enum.TryParse(parameter.ToString(), out note))
    {
        _vm.AddOrUpdateNote(note, Keyboard.Modifiers);
    }
    else
    {
        ...
    }
}

我的 ViewModel 的一部分:

public void AddOrUpdateNote(Notes note, ModifierKeys mKeys)
{
    if (mKeys == ModifierKeys.Control)
    {
        ...
    }
    else if (mKeys == ModifierKeys.Shift)
    {
        ...
    }
    else
    {
        ...
    }
}

因此,根据按下哪个修饰键,会有细微的行为差异。(拆分成不同的方法对我来说感觉很糟糕)


更新:我已经阅读了一些解释InputGestures。在http://msdn.microsoft.com/en-us/library/ms752308%28v=vs.110%29.aspx据说this.InputBindings.Add(Blabla)(我猜来自 xaml.cs),它可以在 ViewModel 中完成吗?或者它是否严格需要通过 XAML 完成,所以,如果我的应用程序中有很多组合键,例如上面的示例,它仍然需要以“长”方式完成吗?

如果可能,请提供一些代码示例,以便我更好地理解它。谢谢

(不太清楚怎么问,所以请随时澄清)

4

2 回答 2

2

如果您的唯一目标是减少手动 KeyBinding 的数量,您可以执行以下操作:

var keys = new List<Key> { Key.Space, Key.OemPeriod, Key.D1, [...]};
foreach(var key in keys)
{
     this.InputBindings.Add(new KeyBinding() { Command = MyCommandClass.KeyboardCommand, CommandParameter = key});
]

但我不喜欢这种方法,因为它需要您自己实现命令的委派,而不是让 WPF 来做。您将需要打开 CommandParameter 和修饰键。

以上绝对可行,但是让一个命令完成所有工作对我来说似乎违反直觉。我将实现几个命令(如 AddNoteCommand),以便它们每个都可以拥有自己的 Execute 和 CanExecute 方法。

是的,每个命令你会有几行额外的代码,但你的命令实现不必知道你是如何访问命令的。想象一下,您想将这些命令作为菜单项或按钮添加到您的 UI 中。

我可能缺少一些东西(我不知道命令的作用),但我真的无法想象我会选择这种方法的场景。

但这并不一定会出错;)

于 2014-07-05T21:06:23.533 回答
0

实际上,您可以在附加属性周围使用一个技巧。应用附加属性的语法实际上只是从 XAML 调用特定类的静态函数的“语法糖”。知道了这一点,您可以构建一个“实用程序”类,该类具有一系列可以使用附加属性语法从 XAML 调用的方法。

因此,你可以做这样的事情......

public namespace My{

    public static class Util {

        [AttachedPropertyBrowsableForType(typeof(KeyBinding))]
        public static void SetSet(KeyBinding keyBinding, string bindingData){

            // Add code here to parse the string and do with it what you will.
            // For instance, you can split it on a pipe character to get the modifier,
            // parameter and key, then just apply it to the passed-in keyBinding here.
            // I'll leave this part as an exercise for you to research.
        }
    }
}

你可以像这样使用它......

<Window ...>
    <Window.InputBindings>
        <KeyBinding my:Util.Set="Control|D1|N1" />
        <KeyBinding my:Util.Set="Control|D2|N2" />
        <KeyBinding my:Util.Set="Control|D3|N3" />

        ...

    </Window.InputBindings>
</Window>

笔记:

  • 支持附加属性的方法名称是Set[PropertyName]在“拥有”类上命名的静态方法。在 XAML 中使用它时,它看起来像OwningClass.PropertyName="bla". 在我的示例中,通过调用类Util和静态方法SetSet,“属性名称”变成了“属性名称” Set,因此在 XAML 中(“我的”是导入的 xmlns 值),看起来my:Util.Set="bla"更清楚地读取了我的意图。

  • 我更喜欢数据类型string,因此您可以在一个值中传递大量信息,然后按照您认为合适的方式对其进行解析。但是你可以使用任何你想要的数据类型。例如,您可以采用一个CommandInfo公开您的Modifiers,KeyParameter属性的类,然后创建一个MarkupExtension来“创建”该类并将它们作为构造函数参数,然后通过附加的属性语法设置它,如下所示:

<InputBinding my:Util.Set="{my:CommandInfo Control, D1, N1}" ... />

事实证明,这种附加属性语法在简化 XAML 方面非常出色。例如,我使用这些技术来更轻松地配置我的网格布局。例如,而不是这个......

<Grid>

    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <TextBlock Grid.Row="1" Grid.Column="1", Grid.ColumnSpan="2" />

</Grid>

我现在只能这样做...

<Grid is:GridUtil.Layout="Auto,Auto,Auto|Auto,*">

    <TextBlock is:GridUtil.Cell="1,1s2" />

</Grid>

笔记:

  • 布局是逗号分隔的行高列表、竖线字符,然后是逗号分隔的列宽列表
  • 单元格是一行(可能是带有's N '的行跨度),一个逗号,然后是一列(可能是带有's N '的列跨度)希望这会有所帮助!
于 2021-01-05T07:44:15.143 回答