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

时间:2015-11-10 11:30:45

标签: 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光的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轻量级框架以某种方式获得旧行为吗?

1 个答案:

答案 0 :(得分:3)

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.3722 2 ,我会说您正在使用4.0库。这就是为什么我认为引用4.5版本会解决它。

不幸的是,我无法通过查看source code找出为什么两个版本不同。 .NET 4.0 version of the project中没有定义这三个常量,为什么不用CommandManager生成分支?