wpf 使用 Action<> 和 Func<> 的命令
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16186828/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Commands using Action<> and Func<>
提问by mcalex
I am working through MVVM Survival Guide for Enterprise Architectures in Silverlight and WPFand have hit a snag in the Command section. Specifically, it creates a command based on an Action<object> and Func<object, bool>. At a point where I'm supposed to 'build and run the application', I am instead getting compile errors.
我正在研究Silverlight 和 WPF 中企业架构的 MVVM 生存指南,并在命令部分遇到了障碍。具体来说,它基于 Action<object> 和 Func<object, bool> 创建一个命令。在我应该“构建和运行应用程序”的时候,我却收到了编译错误。
The command stuff:
命令的东西:
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);
}
...
}
The method call stuff:
方法调用的东西:
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);
}
I get wavy blue lines under the new Command(ShowCustomerDetails, IsCustomerSelected))bit with a 'The best overloaded match for Northwind.Application.Command.Command(System.Action<object>, System.Func<object, bool>)has some invalid arguments'.
我new Command(ShowCustomerDetails, IsCustomerSelected))在位下方出现蓝色波浪线,并显示“最佳重载匹配Northwind.Application.Command.Command(System.Action<object>, System.Func<object, bool>)有一些无效参数”。
When I try to compile, I get the above error, plus two messages:
当我尝试编译时,出现上述错误,以及两条消息:
Argument 1: Cannot convert from method group to System.Action<object>
Argument 2: Cannot convert from method group to System.Func<object, bool>
Now, I know a lot moreabout Actions and Funcs than I did yesterday, and can almost bypass the errrors by changing the command declaration to:
现在,我比昨天更了解 Actions 和 Funcs,并且几乎可以通过将命令声明更改为以下内容来绕过错误:
private readonly Action _execute;
private readonly Func<bool> _canExecute;
and doing similar throughout the code, but then I get an error saying I haven't implemented ICommandproperly.
并在整个代码中做类似的事情,但后来我收到一条错误消息,说我没有ICommand正确实施。
To save my forehead/the nearest wall, can somebody either tell me what I haven't done right so I can fix it, or that the given (book) code is leading me awry, so I can move on.
为了保存我的前额/最近的墙,有人可以告诉我我没有做对什么以便我可以修复它,或者给定的(书)代码导致我出错,所以我可以继续前进。
回答by DHN
Well that's because
那是因为
private bool IsCustomerSelected()
{
return !string.IsNullOrEmpty(SelectedCustomerID);
}
is not of type Func<object, bool>but of Func<bool>. It should look like
不是类型Func<object, bool>而是Func<bool>。它应该看起来像
private bool IsCustomerSelected(object param)
{
return !string.IsNullOrEmpty(SelectedCustomerID);
}
You could use Predicate<object>instead , which is, at least for me, more clear, how the signature should look like.
您可以Predicate<object>改用 ,这至少对我来说更清楚,签名应该是什么样子。
回答by Gennady Vanin Геннадий Ванин
It should be tip top after you substitute your Commandclass to the code below
将您的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()); }
}
Checked this on the code from the mentioned book (p.205, Chapter 5)
在上述书中的代码上检查了这一点(第 205 页,第 5 章)
- Vice R., Shujaat Siddiqi M. - MVVM Survival Guide for Enterprise Architectures in Silverlight and WPF, PACKT Publishing, ISBN 978-1-84968-342-5, 2012
- Vice R., Shujaat Siddiqi M. - Silverlight 和 WPF 中企业架构的 MVVM 生存指南,PACKT Publishing,ISBN 978-1-84968-342-5,2012
This is the error/typo in text of book
这是书中的错误/错别字
Really, in the accompanying code to this book which anyone can get from Download the support files for this book, the correct RelayCommandclass is used instead of Commandclass in the text of the book, according to which I made changes above to Commandclass
真的,在本书随附的代码中,任何人都可以从下载本书的支持文件中获得,在本书的文本中RelayCommand使用了正确的类而不是Command类,我根据这些对Command类 进行了更改
BTW, it is absent in online errata to the book
顺便说一句,这本书的在线勘误表中没有
Response to @DHN comment
对@DHN 评论的回应
Changing to IsCustomerSelected()method to IsCustomerSelected(object param)will bring
更改为IsCustomerSelected()方法IsCustomerSelected(object param)将带来
on ShowCustomerDetailsin following snippet (it is after "The method call stuff:" in question):
就ShowCustomerDetails在下面的代码片断(它是继“方法调用的东西:”有问题):
private Command _showDetailsCommand;
public Command ShowDetailsCommand
{
get
{
return _showDetailsCommand ??
(_showDetailsCommand =
new Command
(
ShowCustomerDetails,//error
IsCustomerSelected
)
);
}
}
the error:
错误:
Expected a method with 'void ShowCustomerDetails(object)' signature
需要一个带有“void ShowCustomerDetails(object)”签名的方法
since ShowCustomerDetails()is:
因为ShowCustomerDetails()是:
public void ShowCustomerDetails()
{
if (!IsCustomerSelected())
throw new InvalidOperationException("Unable to display customer details. "
+ "No customer selected.");
}
and if to change the latter ShowCustomerDetails(object param)this brings more changes and more necessities to change the code with each sequential change.
如果要更改后者,ShowCustomerDetails(object param)这会带来更多更改,并且需要在每次连续更改时更改代码。
Just run the code and try incorporate your change to see what it would invoke
只需运行代码并尝试合并您的更改以查看它会调用什么
回答by cat_minhv0
Action, Func is the way C# design for implementation of closure. Action means that you have closure with parameter object and return System.Voidtype. Func is the way to implement closure with parameter object and return System.Booltype.
Action、Func 是 C# 设计中实现闭包的方式。Action 意味着您拥有带参数对象的闭包并返回System.Void类型。Func 是通过参数对象实现闭包并返回System.Bool类型的方式。
For more detail about closure in C#, see The beauty of closure by Jon Skeet
有关 C# 中闭包的更多详细信息,请参阅Jon Skeet 的闭包之美

