2012-08-05 75 views
6

我目前正在学习WPF和MVVM,我想我得到它的大部分和它是如何工作的,但我遇到了使用RelayCommand(或DelegateCommand)的东西,我不明白。我认为这与代表们的工作方式有关。继电器命令和无参数执行方法

请注意下面的代码目前都在测试解决方案中,所以没有实时代码。另外我正在考虑这个不需要像close这样的参数的命令,并且理解它为什么起作用。

所以,如果我走RelayCommand该约什史密斯创建(http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030)我可以设置这样一个命令:

RelayCommand updateTextContentCommand; 

public ICommand UpdateTextContentCommand 
{ 
    get 
    { 
     if (updateTextContentCommand == null) 
     { 
      updateTextContentCommand = new RelayCommand(
       param => this.UpdateTextContentCommand_Execute()); 
     } 
     return updateTextContentCommand; 
    } 
} 

与此执行方法:

public void UpdateTextContentCommand_Execute() 
{ 
    this.TextContent = DateTime.Now.ToString(); 
} 

我用一个简单的结合一个TextBlock来查看结果并将该命令绑定到一个按钮。这工作正常。我没有得到的是使用lambda表达式来创建命令。 Action<object>需要一个参数不是吗?那么为什么这个代码工作?

如果我改变上面的代码

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute()); 
} 

我得到这些错误:

*为最佳重载方法匹配 'MVVM.RelayCommandTesting.Framework.RelayCommand.RelayCommand(System.Action)'有一些无效参数

参数1:无法从“空”到“System.Action” *

和取出()转换后执行给出了这样的错误:

参数1:无法从“方法组”转换为“System.Action”

但是,如果我改变这样的代码:

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute); 
} 

public void UpdateTextContentCommand_Execute(object param) 
{ 
    this.TextContent = DateTime.Now.ToString(); 
} 

它符合并运行良好。如果我改变视图来使用CommandParameter,那么我可以使用param来设置使用这种方法的文本内容,但是如果我使用lambda样式,我必须将一个参数传递给该行,所以它的参数=>this.UpdateTextContentCommand_Execute(param)

在我的测试中,我对CommandParameter值进行了硬编码,但我想它很可能是数据绑定到实际系统中的ViewModel的属性,因此您可以在lambda样式中传递该参数。

任何人都可以解释为什么无参数版本使用lambda样式吗?

感谢您花时间阅读本文。

看来下面的问题也有关于lambda的一些问题,但我没有看到它回答了我的问题。

Passing a parameter using RelayCommand defined in the ViewModel (from Josh Smith example)

+0

+1为证明你已经尝试过的东西了详细的问题。 – 2012-08-05 12:54:24

+0

干杯。当我发现问题时,我总是努力并付出努力,因为我在寻找答案时发现了有用的问题。 – Kioshiki 2012-08-05 12:59:24

回答

8

构造符参数是具有以下签名的委托:

void MethodName(T parameter) 

其中参数是T型的(在RelayCommand的情况下,这将是system.Object类型的

此编号:

param => this.UpdateTextContentCommand_Execute() 

lambda表达,基本上扩展到这一点:

void AnonymousMethod(object param) 
{ 
    this.UpdateTextContentCommand_Execute(); 
} 

因此,在这种情况下,你传递你只是不使用它的参数(param)。 如果你明白这一点,那么你现在应该知道为什么你的其他例子表现他们的方式。

实施例1

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute()); 
} 

这里你正在调用返回空隙的方法。构造函数期待的是,Action<T>委托因此错误匹配的东西。

实施例2

如果随后删除这样的括号:

if (updateTextContentCommand == null) 
{ 
    updateTextContentCommand = new RelayCommand(
     this.UpdateTextContentCommand_Execute); 
} 

将这看作是有点像订阅的事件:

myObject.myevent += new Action<object>(this.UpdateTextContentCommand_Execute); 

其可以缩短为:

myObject.myevent += this.UpdateTextContentCommand_Execute; 

所以构造函数接受具有签名,IE浏览器

void UpdateTextContentCommand_Execute(object parameter) 

你的方法Action<T>委托签名相匹配的任何方法具有以下特征:

void UpdateTextContentCommand_Execute() 

正如你所看到的签名唐不匹配,所以编译器抱怨。

当您更新UpdateTextContentCommand_Execute方法接受一个对象参数是签名匹配现在这就是为什么它现在的作品。

+0

谢谢,你所花费的实例方法(AnonymousMethod)使这一切水到渠成我。我认为这是一个'看不到树木'的情况。我没有使用过多的lambda表达式,但是我已经使用了Linq。我只是想看到连接。 – Kioshiki 2012-08-05 12:51:42

+0

我有完全相同的问题。当我有那个'啊哈'的时刻,一切都落空了,突然之间lambda表达式变得更容易理解。我很高兴能够以帮助别人的方式表达我的经历。 – 2012-08-05 12:53:42