c# - 在 MVVM Light 5.2.0.37222 中找不到 GalaSoft.MvvmLight.CommandWpf 命名空间

标签 c# wpf mvvm mvvm-light relaycommand

我刚刚尝试将我的一个 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...");
    }
}

View 的 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>

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

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

最佳答案

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

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

In the portable class library version of MVVM Light, there is no CommandManager.

...

The first obvious solution I considered was this: Move the RelayCommand out of the GalaSoft.MvvmLight.dll assembly and into the GalaSoft.MvvmLight.Platform.dll. Because this DLL is not a PCL (hence the “platform” name), it can contains platform-specific elements. If I move the RelayCommand there, it will work with the CommandManager just like before. However, it will not be available for PCL-based assemblies anymore, which is a real issue. That’s why I decided against this decision.

Instead, I decided to duplicate the RelayCommand class. If you check the WPF source code, you will see that this class is linked in the GalaSoft.MvvmLight assembly, and also in the GalaSoft.MvvmLight.Platform assembly. This is the same class! To avoid conflicts however, the one in the Platform assembly is declared in the GalaSoft.MvvmLight.CommandWpf namespace.

在这种背景下,我仍然对为什么事情会变成现在这样感到有点困惑。当我反汇编发布在 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 生成分支呢?

关于c# - 在 MVVM Light 5.2.0.37222 中找不到 GalaSoft.MvvmLight.CommandWpf 命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33628982/

相关文章:

c# - 将字节数组转换为内存流和位图导致内存使用率高

c# - 在 C# 代码中创建元素时出现 WPF 绑定(bind)错误

WPF 用户控件 HitTest

iOS MVVM 如何将数据从 subview 模型传递到父 View 模型

javascript - KnockoutJS 绑定(bind)到键/值对

c# - 从 ViewModel 了解数据绑定(bind)

c# - 从相机设备获取数字

c# - 在 .NET 4.0 之前的 C# 中,是否有一种安全的方法来执行指针运算?

wpf - 使用 InvokeCommandAction MVVM 传递参数

wpf - 依赖属性 - 如何添加所有者以使其充当附加属性?