【问题标题】:How to use ApplicationCommands in MVVM如何在 MVVM 中使用 ApplicationCommands
【发布时间】:2016-01-26 20:23:58
【问题描述】:

我想使用 ApplicationCommands。剪切、复制、粘贴、保存……它们看起来很有趣,因为命令路由、键绑定以及某些控件使用它们的事实。我了解如何绑定到我的 VM 上的中继/委托命令,但我似乎无法理解应用程序命令。我找到了几个旧答案,但没有其他信息,我有点不愿意遵循这些路线。

这似乎很常见,但信息似乎非常有限。这通常是如何实现的? (使用或不使用 PRISM、MVVM Light 等)

旧答案:

How to bind ApplicationCommands to a ViewModel 但这对我来说使用行为来解决这个问题似乎很奇怪

WPF - Handle an ApplicationCommand in the ViewModel 但我认为这不是已接受答案中的 MVVM。

在旧文章中使用附加属性:CommandBindings with MVVM 引用另一篇文章。

【问题讨论】:

  • 很抱歉没有时间详细回答,但您的第一个链接在正确的轨道上。那里的示例将行为与视图模型紧密耦合(this:AssociatedObject.SelectedItem as NestingItemTreeViewModelBase;)。这可以防止行为真正可重用。您应该公开 ICommand 依赖属性,而不是强制转换。您将这些 DP 绑定到包含命令逻辑的 ViewModel,然后将应用程序命令中继到绑定到此 DP 的命令。这将符合 MVVM 模式。希望能给你一个方向
  • 您能否详细说明这部分:“然后将应用程序命令中继到绑定到此 DP 的命令”?另外,我不需要用户控件,那么这些依赖属性去哪里了?
  • 您也可以将 DP 添加到行为中。它们也源自DependencyObject,就像所有 WPF 控件一样。在内部,即CopyCommandCanExecute,您分别调用e.CanExecute = CopyCommand.CanExecute(null)CopyCommand.Execute(null)CopyCommand 是 CopyCommand DP 的包装器)。在 Xaml 中,您将 ViewModel 绑定到它`

标签: c# wpf mvvm


【解决方案1】:

我问这个问题已经有一段时间了,但看起来很多人都在关注它。我最终使用了一种将 VM 命令列表连接到 FrameworkElement 的行为。这似乎是最灵活和可重复使用的解决方案。

public class AttachCommandBindingsBehavior : Behavior<FrameworkElement>
{
    public ObservableCollection<CommandBinding> CommandBindings
    {
        get
        {
            return (ObservableCollection<CommandBinding>)GetValue(CommandBindingsProperty);
        }
        set
        {
            SetValue(CommandBindingsProperty, value);
        }
    }
    public static readonly DependencyProperty CommandBindingsProperty = DependencyProperty.Register("CommandBindings", typeof(ObservableCollection<CommandBinding>), typeof(AttachCommandBindingsBehavior), new PropertyMetadata(null, OnCommandBindingsChanged));

    private static void OnCommandBindingsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        AttachCommandBindingsBehavior attachCommandBindingsBehavior = (AttachCommandBindingsBehavior)sender;

        if (attachCommandBindingsBehavior == null)
            return;

        ObservableCollection<CommandBinding> commandBindings = (ObservableCollection<CommandBinding>)e.NewValue;

        if (commandBindings != null)
        {
            if (attachCommandBindingsBehavior.CommandBindings != null)
                attachCommandBindingsBehavior.CommandBindings.CollectionChanged -= attachCommandBindingsBehavior.CommandBindings_CollectionChanged;

            attachCommandBindingsBehavior.CommandBindings.CollectionChanged += attachCommandBindingsBehavior.CommandBindings_CollectionChanged;
        }
    }

    void CommandBindings_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        ObservableCollection<CommandBinding> collection = (ObservableCollection<CommandBinding>)sender;

        if (collection != null)
        {
            foreach (CommandBinding commandBinding in collection)
                AssociatedObject.CommandBindings.Add(commandBinding);
        }
    }
}

在 xaml 中你可以这样做:

<i:Interaction.Behaviors>
    <localBehaviors:AttachCommandBindingsBehavior CommandBindings="{Binding CommandBindings}"/>
</i:Interaction.Behaviors>

【讨论】:

  • 对于使用此行为的任何人,请知道它已损坏,并且仅在添加命令绑定之后 行为被附加(几乎从未如此)时才有效。另一个用户对此实现有疑问,我发布了一个modified version,它应该可以更可靠地工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-08
  • 1970-01-01
  • 1970-01-01
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
  • 2022-11-14
相关资源
最近更新 更多