我只是尝试将我的一个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轻量级框架以某种方式获得旧行为吗?
答案 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
生成分支?