Wpf 视图模型中的RoutedUICommand与ICommand的比较&;使用输入绑定

Wpf 视图模型中的RoutedUICommand与ICommand的比较&;使用输入绑定,wpf,xaml,data-binding,icommand,Wpf,Xaml,Data Binding,Icommand,基本的ICommand接口实现(如DelegateCommand和RelayCommand)缺少RoutedCommand类中包含的InputSignatures属性。此属性支持绑定到键手势,RoutedUICommand中的Text属性支持设置控件的标题。例如: <MenuItem Header="File"> <MenuItem Command="Open" /> 结果是在文件菜单项下出现一个标签为“Open Ctrl+O”的菜单项。对于手势,将把输入gue

基本的ICommand接口实现(如DelegateCommand和RelayCommand)缺少RoutedCommand类中包含的InputSignatures属性。此属性支持绑定到键手势,RoutedUICommand中的Text属性支持设置控件的标题。例如:

<MenuItem Header="File">
  <MenuItem Command="Open" />

结果是在文件菜单项下出现一个标签为“Open Ctrl+O”的菜单项。对于手势,将把输入guesture映射到命令,但您失去了InputGestureText支持


在为XAML或视图模型中的命令定义键手势和文本时,如何保持绑定到视图模型的ICommand的简单性?例如,我希望在上下文菜单和主菜单中显示一个命令,以显示RoutedUICommand所支持的相同标题和InputGestureText,但该命令的实现在视图模型内部,而不是在窗口的代码后面。

查看reflector中的
菜单项
,我们可以看到菜单项如何拾取
标题
/
输入手势
值,即:

private static object CoerceInputGestureText(DependencyObject d, object value)
{
    RoutedCommand command;
    MenuItem item = (MenuItem) d;
    if ((string.IsNullOrEmpty((string) value) &&
        !item.HasNonDefaultValue(InputGestureTextProperty)) &&
        ((command = item.Command as RoutedCommand) != null))
    {
        InputGestureCollection inputGestures = command.InputGestures;
        // Get appropriate gesture....
    }
    return value;
}
有类似的代码基于当前命令强制Header属性,但在本例中,它会查找
RouteDuicCommand
。这告诉我们,这些命令必须是
RoutedCommand
/
routedICommand
的实例,才能利用
MenuItem
的此功能

查看reflector中的
RoutedCommand
,创建源自
RoutedCommand
DelegateCommand
不是一个简单的方法,因为它是
CanExecute
/
Execute
方法不是虚拟的

我们可以编写如下代码:

public class DelegateCommand : RoutedCommand, ICommand
{
    bool ICommand.CanExecute(object parameter) {
        // Insert delegate can execute logic
    }
    void ICommand.Execute(object parameter) {
        // Insert delegate execute logic
    }
}
但这并不阻止调用
RoutedCommand
上的非显式
CanExecute
/
Execute
方法。这可能是问题,也可能不是问题

或者,我们可以创建一个定制的
MenuItem
,它足够智能,可以查找我们的DelegateCommand(或其他地方),并使用它的文本/手势

public class MyMenuItem : MenuItem {

    static MyMenuItem() {
        InputGestureTextProperty.OverrideMetadata(typeof(MyMenuItem),
            new FrameworkPropertyMetadata(string.Empty, null, CoerceInputGestureText));
    }

    private static object CoerceInputGestureText(DependencyObject d, object value) {
        MenuItem item = (MenuItem)d;
        var command = item as DelegateCommand;
        if ((string.IsNullOrEmpty((string)value) &&
            DependencyPropertyHelper.GetValueSource(item, InputGestureTextProperty).BaseValueSource == BaseValueSource.Default &&
            command != null) {
            InputGestureCollection inputGestures = command.InputGestures;
            // Get appropriate gesture....
        }

        // Call MenuItem Coerce
        var coerce = InputGestureTextProperty.GetMetadata(typeof(MenuItem)).CoerceValueCallback;
        return coerce(d, value);
    }

}

我遇到过这个问题,但并不重要。我想使用某种附加属性用法,将ICommand链接到手势。请让我知道你在这个问题上的进展。