我正在MVVM Survival Guide for Enterprise Architectures in Silverlight and WPF工作,并且在命令部分遇到了麻烦。具体而言,它基于Action< object>创建命令。和Func< object,bool>。在我应该“构建并运行应用程序”的时候,我反而遇到了编译错误。
命令:
public class Command : ICommand
{
private readonly Action<object> _execute;
private readonly Func<object, bool> _canExecute;
public Command(Action<object> execute, Func<object, bool> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public void Execute(object parameter)
{
_execute(parameter);
}
public bool CanExecute(object parameter)
{
return (_canExecute == null) || _canExecute(parameter);
}
...
}
方法调用东西:
private Command _showDetailsCommand;
public Command ShowDetailsCommand
{
get
{
return _showDetailsCommand
?? (_showDetailsCommand
= new Command(ShowCustomerDetails, IsCustomerSelected));
}
}
public void ShowCustomerDetails()
{
if (!IsCustomerSelected()){
throw new InvalidOperationException("Unable to display customer details. "
+ "No customer selected.");
}
CustomerDetailsTabViewModel customerDetailsViewModel =
GetCustomerDetailsTab(SelectedCustomerID);
if (customerDetailsViewModel == null)
{
customerDetailsViewModel
= new CustomerDetailsTabViewModel
(_dataProvider,
SelectedCustomerID);
Tabs.Add(customerDetailsViewModel);
}
SetCurrentTab(customerDetailsViewModel);
}
private bool IsCustomerSelected()
{
return !string.IsNullOrEmpty(SelectedCustomerID);
}
我在new Command(ShowCustomerDetails, IsCustomerSelected))
位下面有一条波浪蓝线,'Northwind.Application.Command.Command(System.Action<object>, System.Func<object, bool>)
的最佳重载匹配有一些无效的参数'。
当我尝试编译时,我得到上述错误,加上两条消息:
Argument 1: Cannot convert from method group to System.Action<object>
Argument 2: Cannot convert from method group to System.Func<object, bool>
现在,我知道关于Actions和Funcs的内容比我昨天做的更多,并且几乎可以通过将命令声明更改为:
来绕过错误private readonly Action _execute;
private readonly Func<bool> _canExecute;
并在整个代码中执行类似操作,但后来我收到错误消息,说我没有正确实现ICommand
。
为了保存我的额头/最近的墙,有人可以告诉我我做的不对,所以我可以解决它,或者给定的(书)代码导致我出错,所以我可以继续前进。 / p>
答案 0 :(得分:2)
那是因为
private bool IsCustomerSelected()
{
return !string.IsNullOrEmpty(SelectedCustomerID);
}
不是Func<object, bool>
类型,而是Func<bool>
类型。它应该看起来像
private bool IsCustomerSelected(object param)
{
return !string.IsNullOrEmpty(SelectedCustomerID);
}
您可以使用Predicate<object>
代替,至少对我来说,更清楚,签名应该如何。
答案 1 :(得分:2)
将Command
类替换为下面的代码
public class Command : ICommand
{ //private readonly Action<object> _execute;
private readonly Action _execute;
//private readonly Func<object, bool> _canExecute;
private readonly Func<bool> _canExecute;//instead of prev line
//public Command(Action<object> execute)
public Command(Action execute)//instead of prev line
: this(execute, null)
{ }
//public Command(Action<object> execute,
public Command(Action execute,//instead of prev line
Func<bool> canExecute)//added instead of next line
//Func<object, bool> canExecute)
{ _execute = execute;
_canExecute = canExecute;
}
public void Execute(object parameter)
{
//_execute(parameter);
_execute();//added instead of prev line
}
public bool CanExecute(object parameter)
{ return (_canExecute == null)
//|| _canExecute(parameter);
|| _canExecute();//added instead of prev line
}
public event EventHandler CanExecuteChanged = delegate { };
public void RaiseCanExecuteChanged()
{ CanExecuteChanged(this, new EventArgs()); }
}
在上述书籍(第205页,第5章)的代码中检查了这一点
这是书中
的错误/拼写错误实际上,在本书的随附代码中,任何人都可以从Download the support files for this book获取,根据本书的文本,使用正确的RelayCommand
类代替Command
类。我将其更改为Command
类
顺便说一下,online errata to the book
中没有将IsCustomerSelected()
方法更改为IsCustomerSelected(object param)
会带来
在以下代码段中的ShowCustomerDetails
上(它位于“方法调用内容:”之后):
private Command _showDetailsCommand;
public Command ShowDetailsCommand
{
get
{
return _showDetailsCommand ??
(_showDetailsCommand =
new Command
(
ShowCustomerDetails,//error
IsCustomerSelected
)
);
}
}
错误:
预期带有'void ShowCustomerDetails(object)'签名的方法
因为ShowCustomerDetails()
是:
public void ShowCustomerDetails()
{
if (!IsCustomerSelected())
throw new InvalidOperationException("Unable to display customer details. "
+ "No customer selected.");
}
如果要更改后者ShowCustomerDetails(object param)
,这会带来更多变化和更多必需品,以便在每次顺序更改时更改代码。
只需运行代码并尝试合并您的更改即可查看它将调用的内容
答案 2 :(得分:0)
动作,Func是C#设计实现闭包的方式。 Action表示您使用参数对象进行闭包并返回 System.Void 类型。 Func是使用参数对象实现闭包并返回 System.Bool 类型的方法。
有关C#中闭包的更多详细信息,请参阅The beauty of closure by Jon Skeet