需要帮助了解MVVM Tutorial,RelayCommand

时间:2022-06-22 02:01:49

I am reading http://msdn.microsoft.com/en-us/magazine/dd419663.aspx tutorial

我正在阅读http://msdn.microsoft.com/en-us/magazine/dd419663.aspx教程

i don't understand what the below code is trying to do.

我不明白下面的代码试图做什么。

_saveCommand = new RelayCommand(param => this.Save(), param => this.CanSave ); 

As defined in the realy Command class CanSave should have been a Method with a paramter since it maps to predicate therefore it's correspoding method should have a paramter same is true for action object. Please help understand.

正如在realy Command类中定义的那样,CanSave应该是一个带参数的方法,因为它映射到谓词,因此它的correspoding方法对于action对象应该有一个相同的参数。请帮忙理解。

2 个解决方案

#1


2  

RelayCommand uses functions (more precisely, delegates) passed into its constructor to implement CanExecute and Execute methods.

RelayCommand使用传递给其构造函数的函数(更准确地说,委托)来实现CanExecute和Execute方法。

In this sample two functions are passed. First describes how to save - just call Save method on RelayCommand owner. Another one describes, how to check if saving is possible - just check current state of owner's CanSave property.

在此示例中,传递了两个函数。首先介绍如何保存 - 只需在RelayCommand所有者上调用Save方法。另一个描述了如何检查是否可以保存 - 只需检查所有者的CanSave属性的当前状态。

In this way you don't have to create your own Command class explicitly.

这样您就不必显式创建自己的Command类。

UPD:

UPD:

Thanks, but my questions is Save() is of type Action, defined as Action and as per my understanding Save() should have a parameter in order to work. But some reason it is able to work even without a paramter.

谢谢,但我的问题是Save()是Action类型,定义为Action,根据我的理解,Save()应该有一个参数才能工作。但是有些原因它甚至可以在没有参数的情况下工作。

Ok, let's look at it closer.

好吧,让我们仔细看看吧。

 _saveCommand = new RelayCommand(param => this.Save(), param => this.CanSave ); 

is equivalent of (in syntax of C# v2.0)

相当于(在C#v2.0的语法中)

 _saveCommand = new RelayCommand(
     new Action<object>(delegate(object param){ this.Save(); }), 
     new Func<object,bool>(delegate(object param){ return this.CanSave; })); 

So, you create anonymous functions wrap actual methods leaving to you right to use or not to use their own parameters.

因此,您创建匿名函数包装实际方法,让您使用或不使用自己的参数。

If you want to go deeper, the code above is compiled under the hood to something like:

如果你想更深入,上面的代码是在下面编译的:

 // 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));

Note that compiler can select other strategies for implementing delegates, depending on what values they enclose from surrounding context. E.g. if your anonymous functions referenced some local variables compiler would generate anonymous class that contained those variables and put methods in this class.

请注意,编译器可以选择其他策略来实现委托,具体取决于它们从周围上下文中包含的值。例如。如果您的匿名函数引用了一些局部变量,编译器将生成包含这些变量的匿名类,并将方法放在此类中。

#2


2  

Let us simplify it

First off, RelayCommand is not part of WPF. It is a class inside the WPFlight toolkit, and we are free to write our own implementations of it. It acts as a wrapper on top of the WPF ICommand, and provides two aspects: action and predicate. The predicate part can be used, for example to enable or disable a button based on some condition. The action part shall contain the logic that should run when the command is executed.

首先,RelayCommand不是WPF的一部分。它是WPFlight工具包中的一个类,我们可以*编写它们自己的实现。它充当WPF ICommand之上的包装器,并提供两个方面:action和谓词。可以使用谓词部分,例如基于某些条件启用或禁用按钮。操作部分应包含执行命令时应运行的逻辑。

As with most concepts, this too has many possible approaches.

与大多数概念一样,这也有许多可能的方法。

Approach 1

方法1

Write explicit named methods for action and predicate. Sample code below

为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
    }        
}

Approach 2

方法2

Here we shall use anonymous methods. This reduces many lines of code and makes the whole code more readable.

这里我们将使用匿名方法。这减少了许多代码行,使整个代码更具可读性。

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;
        }
    }
}

Approach 3

方法3

Make use of lambda expressions, well, almost fully

很好地利用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;
        }
    }
}

#1


2  

RelayCommand uses functions (more precisely, delegates) passed into its constructor to implement CanExecute and Execute methods.

RelayCommand使用传递给其构造函数的函数(更准确地说,委托)来实现CanExecute和Execute方法。

In this sample two functions are passed. First describes how to save - just call Save method on RelayCommand owner. Another one describes, how to check if saving is possible - just check current state of owner's CanSave property.

在此示例中,传递了两个函数。首先介绍如何保存 - 只需在RelayCommand所有者上调用Save方法。另一个描述了如何检查是否可以保存 - 只需检查所有者的CanSave属性的当前状态。

In this way you don't have to create your own Command class explicitly.

这样您就不必显式创建自己的Command类。

UPD:

UPD:

Thanks, but my questions is Save() is of type Action, defined as Action and as per my understanding Save() should have a parameter in order to work. But some reason it is able to work even without a paramter.

谢谢,但我的问题是Save()是Action类型,定义为Action,根据我的理解,Save()应该有一个参数才能工作。但是有些原因它甚至可以在没有参数的情况下工作。

Ok, let's look at it closer.

好吧,让我们仔细看看吧。

 _saveCommand = new RelayCommand(param => this.Save(), param => this.CanSave ); 

is equivalent of (in syntax of C# v2.0)

相当于(在C#v2.0的语法中)

 _saveCommand = new RelayCommand(
     new Action<object>(delegate(object param){ this.Save(); }), 
     new Func<object,bool>(delegate(object param){ return this.CanSave; })); 

So, you create anonymous functions wrap actual methods leaving to you right to use or not to use their own parameters.

因此,您创建匿名函数包装实际方法,让您使用或不使用自己的参数。

If you want to go deeper, the code above is compiled under the hood to something like:

如果你想更深入,上面的代码是在下面编译的:

 // 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));

Note that compiler can select other strategies for implementing delegates, depending on what values they enclose from surrounding context. E.g. if your anonymous functions referenced some local variables compiler would generate anonymous class that contained those variables and put methods in this class.

请注意,编译器可以选择其他策略来实现委托,具体取决于它们从周围上下文中包含的值。例如。如果您的匿名函数引用了一些局部变量,编译器将生成包含这些变量的匿名类,并将方法放在此类中。

#2


2  

Let us simplify it

First off, RelayCommand is not part of WPF. It is a class inside the WPFlight toolkit, and we are free to write our own implementations of it. It acts as a wrapper on top of the WPF ICommand, and provides two aspects: action and predicate. The predicate part can be used, for example to enable or disable a button based on some condition. The action part shall contain the logic that should run when the command is executed.

首先,RelayCommand不是WPF的一部分。它是WPFlight工具包中的一个类,我们可以*编写它们自己的实现。它充当WPF ICommand之上的包装器,并提供两个方面:action和谓词。可以使用谓词部分,例如基于某些条件启用或禁用按钮。操作部分应包含执行命令时应运行的逻辑。

As with most concepts, this too has many possible approaches.

与大多数概念一样,这也有许多可能的方法。

Approach 1

方法1

Write explicit named methods for action and predicate. Sample code below

为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
    }        
}

Approach 2

方法2

Here we shall use anonymous methods. This reduces many lines of code and makes the whole code more readable.

这里我们将使用匿名方法。这减少了许多代码行,使整个代码更具可读性。

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;
        }
    }
}

Approach 3

方法3

Make use of lambda expressions, well, almost fully

很好地利用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;
        }
    }
}