Relay命令和无参数执行方法

Kio*_*iki 6 .net wpf lambda mvvm

我正在学习WPF和MVVM,我想我已经掌握了大部分内容以及它是如何工作的但是我遇到了一些关于使用我不理解的RelayCommand(或DelegateCommand)的事情.我认为这与代表的工作方式有关.

请注意,以下代码目前仅在测试解决方案中,因此没有实时代码.此外,我正在考虑这个不需要参数如close的命令,并了解它为什么工作.

因此,如果我采用Josh Smith创建的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用此execute方法:

public void UpdateTextContentCommand_Execute()
{
    this.TextContent = DateTime.Now.ToString();
}
Run Code Online (Sandbox Code Playgroud)

我使用了一个简单的绑定到TextBlock来查看结果,命令绑定到一个按钮.这很好用.我没有得到的是使用lambda表达式来创建命令.该Action<object>预期参数,不是吗?那么为什么这段代码有效呢?

如果我将上面的代码更改为

if (updateTextContentCommand == null)
{
    updateTextContentCommand = new RelayCommand(
        this.UpdateTextContentCommand_Execute());
}
Run Code Online (Sandbox Code Playgroud)

我收到这些错误:

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

参数1:无法从'void'转换为'System.Action'*

并删除()后Execute给出此错误:

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

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

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

public void UpdateTextContentCommand_Execute(object param)
{
    this.TextContent = DateTime.Now.ToString();
}
Run Code Online (Sandbox Code Playgroud)

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

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

任何人都可以解释为什么无参数版本适用于lambda风格吗?

感谢您抽时间阅读.

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

使用ViewModel中定义的RelayCommand传递参数(来自Josh Smith示例)

Ben*_*ale 9

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

void MethodName(T parameter)
Run Code Online (Sandbox Code Playgroud)

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

这段代码:

param => this.UpdateTextContentCommand_Execute()
Run Code Online (Sandbox Code Playgroud)

是一个lambda表达式,基本上扩展到这个:

void AnonymousMethod(object param)
{
    this.UpdateTextContentCommand_Execute();
}
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,你传递一个参数(param)你只是不使用它.如果您了解这一点,那么您现在应该意识到为什么您的其他示例的行为与他们的行为相同.

例1

if (updateTextContentCommand == null)
{
    updateTextContentCommand = new RelayCommand(
        this.UpdateTextContentCommand_Execute());
}
Run Code Online (Sandbox Code Playgroud)

在这里,您调用返回void的方法.构造函数期望与Action<T>委托匹配的东西因此错误.

例2

如果你然后删除这样的括号:

if (updateTextContentCommand == null)
{
    updateTextContentCommand = new RelayCommand(
        this.UpdateTextContentCommand_Execute);
}
Run Code Online (Sandbox Code Playgroud)

可以认为这有点像订阅事件:

myObject.myevent += new Action<object>(this.UpdateTextContentCommand_Execute);
Run Code Online (Sandbox Code Playgroud)

可以缩短为:

myObject.myevent += this.UpdateTextContentCommand_Execute;
Run Code Online (Sandbox Code Playgroud)

因此,构造函数接受具有任何方法签名的匹配Action<T>代表签字即

void UpdateTextContentCommand_Execute(object parameter)
Run Code Online (Sandbox Code Playgroud)

您的方法具有以下签名:

void UpdateTextContentCommand_Execute()
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,签名不匹配,因此编译器会抱怨.

当您更新UpdateTextContentCommand_Execute方法以接受对象参数时,它的签名现在匹配,这就是它现在工作的原因.