按键绑定 RelayCommand

发布于 2024-07-25 13:09:32 字数 768 浏览 7 评论 0原文

我在我的应用程序中使用 RelayCommand 。 将代码放入视图模型中非常有用,但是如何将击键绑定到我的命令?

RoutedUICommand 有其 InputGestures 属性,这使得当我按下按键时自动调用该命令。 (作为额外的好处,它甚至可以在 MenuItem 中显示击键。)不幸的是,RoatedUICommand 的额外属性没有可重用的接口,因此我无法制作具有相同魔力的 RelayUICommand。

我已经尝试过使用 InputBindings:

<Window.InputBindings>
    <KeyBinding Key="PageUp" Command="{Binding SelectPreviousLayerCommand}"/>
</Window.InputBindings>

但这会导致运行时异常,因为 KeyBinding.Command 不是依赖项属性。 (实际上,它抱怨的是 KeyBinding 甚至不是 DependencyObject。)并且由于我的 RelayCommand 是 ViewModel 上的一个属性(而不是设计 RoutedUICommand 的静态字段),因此数据绑定是我知道的唯一方法从 XAML 引用它。

你们是怎么解决这个问题的? 将击键绑定到 RelayCommand 的最佳方法是什么?

I'm using the RelayCommand in my app. It's great for putting the code in the viewmodel, but how do I bind keystrokes to my command?

RoutedUICommand has its InputGestures property, which makes the command automatically be invoked when I press the keystroke. (As an added bonus, it even makes the keystroke display in the MenuItem.) Unfortunately, there's no reusable interface for RoutedUICommand's extra properties, so I can't make a RelayUICommand that gets the same magic.

I've already tried using InputBindings:

<Window.InputBindings>
    <KeyBinding Key="PageUp" Command="{Binding SelectPreviousLayerCommand}"/>
</Window.InputBindings>

But that gets me a runtime exception, because KeyBinding.Command isn't a dependency property. (Actually, what it complains about is that KeyBinding isn't even a DependencyObject.) And since my RelayCommand is a property on my ViewModel (as opposed to the static field that RoutedUICommand is designed for), databinding is the only way I know of to reference it from XAML.

How have you guys solved this? What's the best way to bind a keystroke to a RelayCommand?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

风轻花落早 2024-08-01 13:09:33

您可以使用 CommandReference 类。

非常优雅的代码并且工作起来很有魅力。

看一下:我该如何将按键与复合 WPF 中的 DelegateCommand 相关联?

它与 RelayCommands 的工作方式相同,但它不会更新您的 CanExecutes,因为 CommandReference 不使用调用 CommandManager.RequerySuggested
要实现自动 CanExecute 重新评估,您所需要做的就是在 CommandReference 类中进行以下更改

public event EventHandler CanExecuteChanged
{
     add { CommandManager.RequerySuggested += value; }
     remove { CommandManager.RequerySuggested -= value; }
}

You can use the CommandReference class.

Very elegant code and works like a charm.

Take a look at: How do I associate a keypress with a DelegateCommand in Composite WPF?

It works the same with RelayCommands, but it won't update your CanExecutes since the CommandReference doesn't use call CommandManager.RequerySuggested
All you need to do to achieve automatic CanExecute reevaluation is do the following change inside the CommandReference class

public event EventHandler CanExecuteChanged
{
     add { CommandManager.RequerySuggested += value; }
     remove { CommandManager.RequerySuggested -= value; }
}
许久 2024-08-01 13:09:33

我在视图模型中创建一个键绑定,将命令和键链接起来,然后

        this.KeyBinding = new KeyBinding();
        //set the properties
        this.KeyBinding.Command = this.Command;
        this.KeyBinding.Key = this.Key;
        //modifier keys may or may not be set
        this.KeyBinding.Modifiers = this.ModifierKeys;

我在视图模型根中创建一个 InputBinding 项的集合,并将它们添加到窗口代码中的 Windows InputBindings 中,以在

     foreach (var item in applicationViewModel.InputBindingCollection) {
        this.InputBindings.Add(item);
     }

其不良形式背后执行操作我知道背后的代码,但我还不知道如何进行绑定,但我仍在研究它。 :) 唯一没有给我的是菜单中的关键命令修饰符列表,但那是即将到来的。

I create a Key binding in my view model that links the command and the Key like so

        this.KeyBinding = new KeyBinding();
        //set the properties
        this.KeyBinding.Command = this.Command;
        this.KeyBinding.Key = this.Key;
        //modifier keys may or may not be set
        this.KeyBinding.Modifiers = this.ModifierKeys;

then i create a collection of InputBinding items in my View Model root and add them to the windows InputBindings in my window's code behind

     foreach (var item in applicationViewModel.InputBindingCollection) {
        this.InputBindings.Add(item);
     }

its bad form to do stuff in the code behind i know, but i dont know how to do the binding yet, however im still working on it. :) The only thing this doent give me is a key command modifer list in the menu, but that is to come.

荒岛晴空 2024-08-01 13:09:33

假设您的 RoutedCommands 是静态定义的:

#region DeleteSelection

    /// <summary>
    /// The DeleteSelection command ....
    /// </summary>
    public static RoutedUICommand DeleteSelection
        = new RoutedUICommand("Delete selection", "DeleteSelection", typeof(ChemCommands));

    #endregion

因此在 XAML 中绑定:

<Canvas.InputBindings>
    <KeyBinding Key="Delete" Command="{x:Static Controls:ChemCommands.DeleteSelection}" />
</Canvas.InputBindings>

此致,

Tim Haughton

Assuming your RoutedCommands are defined statically:

#region DeleteSelection

    /// <summary>
    /// The DeleteSelection command ....
    /// </summary>
    public static RoutedUICommand DeleteSelection
        = new RoutedUICommand("Delete selection", "DeleteSelection", typeof(ChemCommands));

    #endregion

Bind in XAML thus:

<Canvas.InputBindings>
    <KeyBinding Key="Delete" Command="{x:Static Controls:ChemCommands.DeleteSelection}" />
</Canvas.InputBindings>

Regards,

Tim Haughton

烟若柳尘 2024-08-01 13:09:32

我不认为您可以通过 XAML 执行此操作,原因正是您所描述的。

我最终在代码隐藏中完成了它。 虽然它是代码,但它只是一行代码,而且仍然具有相当的声明性,所以我可以接受它。 不过,我真的希望这个问题能够在 WPF 的下一版本中得到解决。

下面是我的一个项目中的示例代码行:

this.InputBindings.Add(new KeyBinding(
    ((MedicContext)this.DataContext).SynchronizeCommand,
    new KeyGesture(Key.F9)));

本例中的 SynchronizeCommand 是 RelayCommand 的一个实例,(显然)F9 会触发它。

I don't think you can do this from XAML, for exactly the reasons you describe.

I ended up doing it in the code-behind. Although it's code, it's only a single line of code, and still rather declarative, so I can live with it. However, I'd really hope that this is solved in the next version of WPF.

Here's a sample line of code from one of my projects:

this.InputBindings.Add(new KeyBinding(
    ((MedicContext)this.DataContext).SynchronizeCommand,
    new KeyGesture(Key.F9)));

SynchronizeCommand in this case is an instance of RelayCommand, and (obviously) F9 triggers it.

长梦不多时 2024-08-01 13:09:32

KeyBinding 类的 Command 属性不支持数据绑定。 这个问题将在 .NET 4.0 中得到解决,您应该能够在即将发布的 .NET 4.0 Beta 2 版本中看到它。

The Command property of the KeyBinding class doesn't support data binding. This issue is going to be solved in .NET 4.0 and you should be able to see it in the coming .NET 4.0 Beta 2 version.

踏月而来 2024-08-01 13:09:32

您可以子类化 KeyBinding,添加一个用于设置 Command 属性的 CommandBinding 依赖属性,然后像任何其他输入绑定一样将其添加到 XAML。

public class RelayKeyBinding : KeyBinding
{
    public static readonly DependencyProperty CommandBindingProperty =
        DependencyProperty.Register("CommandBinding", typeof(ICommand), 
        typeof(RelayKeyBinding),
        new FrameworkPropertyMetadata(OnCommandBindingChanged));
    public ICommand CommandBinding
    {
        get { return (ICommand)GetValue(CommandBindingProperty); }
        set { SetValue(CommandBindingProperty, value); }
    }

    private static void OnCommandBindingChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var keyBinding = (RelayKeyBinding)d;
        keyBinding.Command = (ICommand)e.NewValue;
    }
}

XAML:

<Window.InputBindings>
    <RelayKeyBinding 
        Key="PageUp" 
        CommandBinding="{Binding SelectPreviousLayerCommand}" />
</Window.InputBindings>

You could subclass KeyBinding, add a CommandBinding dependency property that sets the Command property, and then add it to XAML like any other input binding.

public class RelayKeyBinding : KeyBinding
{
    public static readonly DependencyProperty CommandBindingProperty =
        DependencyProperty.Register("CommandBinding", typeof(ICommand), 
        typeof(RelayKeyBinding),
        new FrameworkPropertyMetadata(OnCommandBindingChanged));
    public ICommand CommandBinding
    {
        get { return (ICommand)GetValue(CommandBindingProperty); }
        set { SetValue(CommandBindingProperty, value); }
    }

    private static void OnCommandBindingChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var keyBinding = (RelayKeyBinding)d;
        keyBinding.Command = (ICommand)e.NewValue;
    }
}

XAML:

<Window.InputBindings>
    <RelayKeyBinding 
        Key="PageUp" 
        CommandBinding="{Binding SelectPreviousLayerCommand}" />
</Window.InputBindings>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文