关于wpf:为什么要使用RelayCommand或DelegateCommand而不是仅实现ICommand?

Why use a RelayCommand or DelegateCommand instead of just implementing ICommand?

我只是了解WPF中的MVVM,对于WPF和MVVM都是全新的(我了解它是如何工作的,但从未使用过...)

我在网上找到的每个教程/文章都使用RelayCommand或DelegateCommand。

在我看来,这些模式使VM违反了SRP原则,因为它会将命令逻辑保存在其中。

为什么不只使用ICommand接口的自定义实现? 像这样:

假设您要显示一个人并将其保存到数据库中:

我的Xaml是这样的:

1
2
3
4
5
6
7
8
9
10
11
<StackPanel>                        
    <TextBlock Width="248" Height="24" Text="The name is::" />
    <TextBlock Width="248" Height="24" Text="{Binding Name}">            
    </TextBlock>
    <TextBox HorizontalAlignment="Left" Name="textBox1" Width="120" Height="23"
             VerticalAlignment="Top" Text="{Binding Name}"
             />
    <Button  Name="Salvar" VerticalAlignment="Bottom"
            Command="{Binding SavePerson}"
            CommandParameter="{Binding}">Save</Button>
</StackPanel>

这是我的VM:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class PersonVM: INotifyPropertyChanged
{
    private string nameValue;

    public string Name
    {
        get{
            return nameValue;
        }
        set
        {
            if (value != this.nameValue)
            {
                this.nameValue= value;
                NotifyPropertyChanged("Name");
            }
        }
    }


    public ICommand SavePerson{ get { return new SavePersonCommand(); } }
    #region INotifyPropertyChanged Members


    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    #endregion
}

这是我的命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class SavePersonCommand: ICommand
{      
    #region ICommand Members

    public bool CanExecute(object parameter)
    {
        return (parameter as PersonVM) != null;            
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
            PersonVM person = parameter as PersonVM;
            if(person != null)
                //Actually Save the person...            
    }  


    #endregion
}

我的方法有什么问题?


没什么...但是,如果您有一个真正特定于您的ViewModel的特定命令,而又不想将其公开给其他人,则DelegateCommand很有用,因为它实际上仅适用于您的ViewModel。 我也喜欢DelegateCommands,因为它们不需要您在ViewModel中传递的另一个类,因此编写的代码更少。 如果您提供的ViewModel是一个基本ViewModel,并且可以共享您的Command,则该方法很有用,该ViewModel被大量共享。


如果您不使用某些基本命令(框架的命令或您自己的自定义命令的命令),则会发现自己一次又一次地编写相同的代码。 例如:您不会在自己的命令中引发CanExecuteChanged事件。 实现INotifyPropertyChanged也是一样。 这就是每个人都使用一个或另一个MVVM框架的原因。