我正在阅读http://msdn.microsoft.com/en-us/magazine/dd419663.aspx教程
我不明白以下代码试图做什么。
_saveCommand = new RelayCommand(param => this.Save(), param => this.CanSave );
正如在realy Command类中定义的那样,CanSave应该是一个带参数的方法,因为它映射到谓词,因此它的correspoding方法对于action对象应该有一个相同的参数。请帮助理解。
答案 0 :(得分:2)
RelayCommand
使用传递给其构造函数的函数(更确切地说,委托)来实现CanExecute
和Execute
方法。
在此示例中,传递了两个函数。首先介绍如何保存 - 只需在Save
所有者上调用RelayCommand
方法即可。另一个描述了如何检查是否可以保存 - 只需检查所有者的CanSave
属性的当前状态。
通过这种方式,您无需明确创建自己的Command
类。
UPD:
谢谢,但我的问题是Save()属于Action类型,定义为Action,根据我的理解,Save()应该有一个参数才能工作。但是有些原因它甚至可以在没有参数的情况下工作。
好的,让我们仔细看看吧。
_saveCommand = new RelayCommand(param => this.Save(), param => this.CanSave );
等同于(在C#v2.0的语法中)
_saveCommand = new RelayCommand(
new Action<object>(delegate(object param){ this.Save(); }),
new Func<object,bool>(delegate(object param){ return this.CanSave; }));
因此,您创建匿名函数包装实际方法,让您使用或不使用自己的参数。
如果你想深入了解,上面的代码将在以下内容中编译:
// it is OK to ignore methods arguments.
// So, it's also OK to ignore them in anonymous methods as well
private void Save_Anonymous(object parameter){
this.Save();
}
private bool CanSave_Anonymous(object parameter){
return this.CanSave;
}
....
_saveCommand = new RelayCommand(new Action<object>(this.Save_Anonymous),
new Func<object, bool>(this.CanSave_Anonymous));
请注意,编译器可以选择其他策略来实现委托,具体取决于它们从周围上下文中包含的值。例如。如果你的匿名函数引用了一些局部变量,编译器会生成包含这些变量的匿名类,并将方法放在这个类中。
答案 1 :(得分:2)
首先,RelayCommand不是WPF的一部分。它是WPFlight工具包中的一个类,我们可以自由编写它们自己的实现。 它充当WPF ICommand之上的包装器,并提供两个方面:action和谓词。可以使用谓词部分,例如基于某些条件启用或禁用按钮。动作部分应包含执行命令时应运行的逻辑。
与大多数概念一样,这也有许多可能的方法。
方法1
为action和predicate编写显式命名方法。下面的示例代码
class demoViewModel
{
string filename = "";
private ICommand _saveCommand;
public ICommand SaveCommand
{
get
{
if (_saveCommand== null)
{
_saveCommand = new RelayCommand<object>(
action => Save(filename),
predicate => CanSave(filename));
}
return _saveCommand;
}
}
private bool CanSave(string fname)
{
return (!string.IsNullOrEmpty(fname));
}
private void Save(string fname)
{
SaveHelper(fname);//some logic goes inside SaveHelper
}
}
方法2
这里我们将使用匿名方法。这减少了许多代码行,使整个代码更具可读性。
class demoViewModel1
{
string filename = "";
private ICommand _saveCommand;
public ICommand SaveCommand
{
get
{
if (_saveCommand== null)
{
_saveCommand = new RelayCommand<object>(
action => { SaveHelper(filename); },
predicate => { return (!string.IsNullOrEmpty(filename)); }
);
}
return _saveCommand;
}
}
}
方法3
充分利用lambda表达式
class demoViewModel2
{
string filename = "";
private ICommand _saveCommand;
public ICommand SaveCommand
{
get
{
if (_saveCommand== null)
{
_saveCommand = new RelayCommand<object>(
(objParamForAction) => { SaveHelper(filename); },
() => { return (!string.IsNullOrEmpty(filename)); }
);
}
return _saveCommand;
}
}
}