C# 如何简化XAML中的输入绑定?

C# 如何简化XAML中的输入绑定?,c#,wpf,xaml,mvvm,inputbinding,C#,Wpf,Xaml,Mvvm,Inputbinding,首先,这是我的代码: <Window ...> <Window.Resources> </Window.Resources> <Window.InputBindings> <KeyBinding Key="Space" Command="{Binding KeyboardCommand}" CommandParameter="Space"/> <KeyBinding Key="OemPeriod" Command

首先,这是我的代码:

<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>
我的ViewModel的一部分:

public void AddOrUpdateNote(Notes note, ModifierKeys mKeys)
{
    if (mKeys == ModifierKeys.Control)
    {
        ...
    }
    else if (mKeys == ModifierKeys.Shift)
    {
        ...
    }
    else
    {
        ...
    }
}
所以,有一个小的行为差异取决于哪个修改键被按下。(分裂成不同的方法让我感觉很糟糕)


更新: 我读了一些关于
输入手势的解释。在上面提到的
this.InputBindings.Add(Blabla)
(我猜是来自xaml.cs),它可以在ViewModel中完成吗?或者它严格地需要通过XAML来完成,所以,如果我的应用程序中有大量的键组合,比如上面的例子,它仍然需要以“长”的方式来完成

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


(也不太清楚如何提问,请随时澄清)

如果您的唯一目标是减少手动键绑定的数量,您可以这样做:

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});
]
var keys=newlist{Key.Space,Key.OemPeriod,Key.D1,[…]};
foreach(var键入键)
{
this.InputBindings.Add(new KeyBinding(){Command=MyCommandClass.KeyboardCommand,CommandParameter=key});
]
但我不喜欢这种方法,因为它要求您自己实现命令的委托,而不是让WPF来完成。您需要打开CommandParameter和modifierkey

上面的方法绝对有效,但是让一个命令来完成所有的工作对我来说似乎是违反直觉的。我会实现几个命令(比如AddNoteCommand),这样它们就可以各自持有自己的Execute和CanExecute方法

是的,每个命令都会有几行额外的代码,但您的命令实现不必知道如何访问该命令。假设您希望将这些命令添加为菜单项或UI中的按钮

我可能遗漏了一些东西(我不知道这些命令做什么),但我真的无法想象我会选择这种方法的场景


但这并不一定是错的;)

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

因此,你可以这样做

公共名称空间我的{
公共静态类Util{
[AttachedPropertyBrowsableForType(typeof(KeyBinding))]
公共静态void集合(KeyBinding KeyBinding,string bindingData){
//在这里添加代码来解析字符串,并根据需要使用它。
//例如,可以在管道角色上拆分它以获得修改器,
//参数和键,然后将其应用于此处传入的键绑定。
//我将把这部分作为练习留给你们研究。
}
}
}
你可以这样使用它


...
注:

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

  • 我更喜欢数据类型
    string
    ,因此您可以在一个值中传递大量信息,然后根据需要对其进行解析。但您可以使用任何需要的数据类型。例如,您可以使用一个
    CommandInfo
    类,该类公开您的
    修饰符
    参数
    属性,然后创建一个
    MarkupExtension
    以“创建”该类,并将其作为构造函数参数,然后通过附加的属性语法进行设置,如下所示:

  • 
    
    这个附加属性语法在简化XAML方面被证明是非常惊人的。作为一个例子,我使用这些技术来更容易地配置我的网格布局。例如,代替这个

    
    
    我现在可以这么做了

    
    
    注:

    • 布局是以逗号分隔的行高列表、管道字符,然后是以逗号分隔的列宽列表
    • 单元格是一行(可能是带“sN”的行范围)、一个逗号,然后是一列(可能是带“sN”的列范围) 希望这有帮助

    您使用InputBinding而不是RoutedCommand及其输入手势有什么特殊原因吗?我觉得很奇怪,您共享一个命令/Execute()当WPF有一个专门用于此目的的系统时,方法和处理delagation到命令的实际实现。嗯,实际上我不知道它们。谢谢你的指导,我将对此进行一些阅读。谢谢!@TroelsLarsen请查看我在OpInputBirtations中的更新,这对你来说没有多大帮助您需要创建任何定义。但也不是只有一个命令。无论您做什么,无论您做什么,您都将编写代码来调用实现您的命令的正确方法。我添加了一个答案,减少了关键点,但由于可读性,我决不会在生产中这样做。
    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});
    ]