【问题标题】:Cannot find GalaSoft.MvvmLight.CommandWpf namespace in MVVM Light 5.2.0.37222在 MVVM Light 5.2.0.37222 中找不到 GalaSoft.MvvmLight.CommandWpf 命名空间
【发布时间】:2016-02-11 06:30:16
【问题描述】:

我刚刚尝试将我的一个 WPF 项目从 MVVM Light 4.2.30 更新到 5.2。之后我注意到我的RelayCommands 不再触发他们的CanExecute 方法。

快速搜索后,我找到了几篇解释问题的文章,并建议使用GalaSoft.MvvmLight.CommandWpf 命名空间而不是GalaSoft.MvvmLight.Command。但是我找不到 GalaSoft.MvvmLight.CommandWpf 命名空间。当我在 Visual Studio 的“对象浏览器”中查看 GalaSoft.MvvMGalaSoft.MvvmLight.dll 时,我也找不到这个命名空间。

似乎没有其他人,但我有这个问题 - 知道我做错了什么吗?

更新:

我创建了一个小型示例项目,展示了我当前如何在 MVVM light 版本 4.2.30 中使用 RelayCommands 及其 CanExecute 方法:

public class ViewModel : ViewModelBase
{
    private bool _isReadOnly = false;

    public ViewModel ()
    {
        this.DoSomethingCommand = new RelayCommand(DoSomething, CanDoSomething);
    }

    public bool IsReadOnly
    {
        get
        {
            return _isReadOnly;
        }

        set
        {
            _isReadOnly = value;
            this.RaisePropertyChanged("IsReadOnly");

            // With MVVMLight 4.2.30.23246 I did not need to call the RaiseCanExecuteChanged on any of my RelayCommands
            // DoSomethingCommand.RaiseCanExecuteChanged(); 
        }
    }

    public RelayCommand DoSomethingCommand { get; set; }

    private bool  CanDoSomething()
    {
        return !this.IsReadOnly;
    }

    private void DoSomething()
    {
        MessageBox.Show("Let's break the MVVM idea...");
    }
}

视图的 XAML 代码是:

<Window x:Class="MVVMLight5.2CanExecuteTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:MVVMLight5._2CanExecuteTest"
    mc:Ignorable="d"
    Title="Test" Height="150" Width="200">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <CheckBox HorizontalAlignment="Center" Grid.Row="0" Grid.Column="0" Content="Is read only" IsChecked="{Binding IsReadOnly, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    <Button Grid.Row="1" Grid.Column="0" Content="Break me" Command="{Binding DoSomethingCommand}"/>
</Grid>

我的目标是,如果我在视图中有一个使用“DoSomethingCommand”作为命令的按钮,那么当我的 IsReadOnly 属性设置为 false 时,该按钮应该被禁用。 当使用 MVVM light 4.2.30 时,到目前为止没有任何额外的工作,但在 MVVM light 5.2 中我需要添加 DoSomethingCommand.RaiseCanExecuteChanged();使按钮在视图中处于禁用状态。

我可以通过新的 MVVM 轻框架以某种方式获得旧行为吗?

【问题讨论】:

  • 只有当您引用库的 PCL(便携式)版本时,RelayCommand 类才位于 CommandWpf 命名空间中。当面向 .NET 4.0 及更低版本时,它位于 Command 命名空间中。你确定是 MvvmLight 有错吗?能贴出代码吗?
  • 不,我没有使用便携式版本 - 我正在引用库的常规 4.5 版本。为什么这仅适用于 PCL 版本且仅适用于 .NET 4.0?那我该如何解决我的问题呢?
  • 目前没有找到答案。与此同时,我想知道在当前版本的 MVVM light 中如何调用 CanExecute 方法:手动?也许在一个计时器内?
  • 能否贴出用于绑定命令的代码,以及创建命令的代码和CanExecute 方法本身?我对此没有任何问题,并且我不知道当前没有调用 CanExecute 的任何错误。要么创建一个 SSCCE 来展示错误。
  • 嗨帕特里克!对不起,后来的回答......我已经更新了我的帖子。

标签: c# wpf mvvm mvvm-light relaycommand


【解决方案1】:

TL;DR:确保您有对 GalaSoft.MvvmLight.Platform 的引用,然后您可以使用 CommandWpf 命名空间。或者,仔细检查您是否链接到 .NET 4.5 版本的 MVVM Light;我认为您正在链接到 .NET 4.0 版本

Laurent(MVVMLight 的作者)实际上有addressed all of this on his blog。关于他创建不同命名空间的原因:

在MVVM Light的可移植类库版本中,没有CommandManager。

...

我考虑的第一个明显的解决方案是:将 RelayCommand 从 GalaSoft.MvvmLight.dll 程序集中移到 GalaSoft.MvvmLight.Platform.dll 中。因为此 DLL 不是 PCL(因此称为“平台”名称),它可以包含特定于平台的元素。如果我将 RelayCommand 移到那里,它将像以前一样与 CommandManager 一起使用。但是,它将不再适用于基于 PCL 的程序集,这是一个真正的问题。这就是为什么我决定反对这个决定。

相反,我决定复制 RelayCommand 类。如果您查看 WPF 源代码,您将看到该类在 GalaSoft.MvvmLight 程序集中以及 GalaSoft.MvvmLight.Platform 程序集中链接。这是同一堂课!然而,为避免冲突,Platform 程序集中的一个在 GalaSoft.MvvmLight.CommandWpf 命名空间中声明。

在这种情况下,我仍然有点困惑为什么事情会这样。当我反汇编在 Nuget 上发布的库时,我看到的是:

MvvmLightLibs.5.2.0.0\lib\net40(汇编版本5.2.0.37222):

namespace GalaSoft.MvvmLight.Command
{
    /// <omitted, see below>
    public class RelayCommand<T> : ICommand
    {
        private readonly WeakAction<T> _execute;
        private readonly WeakFunc<T, bool> _canExecute;

        /// <summary>
        /// Occurs when changes occur that affect whether the command should execute.
        /// 
        /// </summary>
        public event EventHandler CanExecuteChanged;

MvvmLightLibs.5.2.0.0\lib\net45(汇编版本5.2.0.37223):

namespace GalaSoft.MvvmLight.Command
{
    /// <omitted, see below>
    public class RelayCommand<T> : ICommand
    {
        private readonly WeakAction<T> _execute;
        private readonly WeakFunc<T, bool> _canExecute;

        /// <summary>
        /// Occurs when changes occur that affect whether the command should execute.
        /// 
        /// </summary>
        public event EventHandler CanExecuteChanged
        {
            add
            {
                if (this._canExecute == null)
                    return;
                CommandManager.RequerySuggested += value;
            }
            remove
            {
                if (this._canExecute == null)
                    return;
                CommandManager.RequerySuggested -= value;
            }
        }

请注意,CanExecuteChanged 的 4.5 版本使用 CommandManager 类,这就是为什么您不需要调用 RaiseCanExecuteChanged()。 4.0版本只是常规活动,需要自己拨打RaiseCanExecuteChanged()

另请注意,两者的程序集版本不同,并且由于在您的问题中您说您使用的是 5.2.0.37222,我会说您使用的是 4.0 库。这就是为什么我认为只需引用 4.5 版本就可以解决问题。

很遗憾,通过查看source code,我无法弄清楚为什么这两个版本不同。这三个常量都没有在.NET 4.0 version of the project 中定义,那么为什么不生成带有CommandManager 的分支呢?

【讨论】:

  • 添加 GalaSoft.MvvmLight.Platform.dll 作为参考允许我使用 GalaSoft.MvvmLight.CommandWpf 命名空间,从而解决了我的问题。我不得不承认,在开始这个话题之前,我一定是有点愚蠢,从一开始就没有理解这一点(我也读过 Laurent 的帖子)。感谢您的帮助,很抱歉给您带来麻烦... :-/
  • 越深入越糊涂,完全可以理解!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-09
  • 2022-11-10
  • 1970-01-01
  • 2019-08-28
  • 2016-02-21
  • 1970-01-01
相关资源
最近更新 更多