在MVVM Light 5.2.0.37222中找不到GalaSoft.MvvvmLight.CommandWpf命名空



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

经过快速搜索,我找到了几篇文章,解释了这个问题,并建议使用GalaSoft.MvvmLight.CommandWpf命名空间而不是GalaSoft.MvvmLight.Command。但是,我找不到GalaSoft.MvvmLight.CommandWpf命名空间。当我在Visual Studio的"对象浏览器"中查看GalaSoft.MvvVMAlaSoft.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灯4.2.30时,到目前为止,这没有任何额外的功能,但在MVVM灯5.2中,我需要添加DoSomethingCommand.RiseCanExecuteChanged();以使该按钮在视图中禁用。

我能用新的MVVM轻框架以某种方式获得旧的行为吗?

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

Laurent(MVVMLight的作者)实际上已经在他的博客上谈到了这一切。关于他为什么创建了一个不同的名称空间:

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

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

相反,我决定复制RelayCommand类。如果您检查WPF源代码,您将看到这个类在GalaSoft.MvvvmLight程序集中链接,也在GalaSoft.mvvvmlight.Platform程序集中链接。这是同一个班!然而,为了避免冲突,平台程序集中的冲突是在GalaSoft.MvvvmLight.CommandWpf命名空间中声明的。

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

MvvvmLightLibs.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;

MvvvmLightLibs.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版本就可以修复它

不幸的是,我无法通过查看源代码来理解为什么这两个版本不同。这三个常量都没有在.NET 4.0版本的项目中定义,那么为什么它不使用CommandManager生成分支呢?

最新更新