轻松通信最佳实践



我已经使用RelayCommands(它们在一个单独的类中)大约一个月了,我觉得它们在声明时有点笨拙。下面我有三种方法可以考虑如何声明RelayCommand

在第一种情况下,我声明我的ICommand,然后在加载ViewModel时,我构造指向代码中某个方法的RelayCommand

public class MyViewModel
{
    public ICommand MyCommand { get; private set; }
    public MyViewModel()
    {
        MyCommand = new RelayCommand(MyMethod, CanMyMethod);
    }
    private void MyMethod()
    {
         // Do something here ...
    }
    private bool CanMyMethod()
    {
         return string.IsNullOrEmpty(MyString) ? false : true;
    }
}

第二种方法是同时做所有事情。

public ICommand MyCommand
    {
        get
        {
            return new RelayCommand(
                () =>
                {
                    // Do something here ...
                },
                () =>
                    string.IsNullOrEmpty(MyString) ? false : true);
        }
    }

现在,我计划在某个ViewModel中编写一个具有相当多Commands的应用程序。我也不能将ViewModel拆分为更小的ViewModel,因为所有的controls都必须协同工作。

所以我的问题是:

  1. 声明和构造ICommands的最佳方法是什么?这是我的方法之一,还是有更简单的方法
  2. 考虑到单个ViewModel中有50多个ICommands,维护每种方法的概述有多难
  3. 我希望将来能在Windows7、8和10上发布我的应用程序。如果我只使用.NET4.5,RelayCommands有什么限制吗
  4. 除了RelayCommands,我还发现了这个项目:Caliburn Micro。它允许您执行类似以下代码的操作。有人知道与RelayCommands相比,这在性能方面有多好吗?这只是一个额外的问题,不需要回答就可以将帖子标记为答案

Xaml(查看)

<Button x:Name="Login" Content="Log in" />

ViewModel

public bool CanLogin(string username, string password)
{
    return !String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password);
}
public string Login(string username, string password)
{
    ...
}

请参阅以下答案。

  1. 声明和构建ICommands的最佳方法是什么?这是我的方法之一,还是有更简单的方法回答:你可以采取联合方法。如果您的execute方法非常小可以使用RelayCommand,否则您可以在中实现自己的ICommand一个单独的类。这将提高视图模型的可读性,因为以及代码的模块化
  2. 考虑到单个ViewModel中有50多个ICommands,维护每种方法的概述有多难。答案:答案1中的封面
  3. 我希望将来能在Windows 7、8和10上发布我的应用程序。如果我只使用.NET4.5,那么RelayCommands有什么限制吗?回答:我看不到Windows 7或8有任何限制,但不确定Windows 10。
  4. 除了RelayCommands,我还发现了这个项目:Caliburn Micro。它允许您执行类似以下代码的操作。有人知道与RelayCommands相比,这在性能方面有多好吗?这只是一个额外的问题,不需要回答就可以将帖子标记为答案。回答:我不确定Caliburn Micro中RelayCommands的源代码。但是如果它使用CommandManager来实现CanExecute功能。然后,命令管理器将在所有用户输入更改时被触发,因此,如果CanExecute方法中有一些重逻辑,这将导致性能问题请参阅CanExecuteCommand是否对性能有任何影响

这是我喜欢的模式,它基本上是方法1:的变体

public class MyViewModel
{
    private readonly RelayCommand myCommand;
    public MyViewModel()
    {
        this.myCommand = new RelayCommand(this.DoStuff, () => ...);
    }
    public ICommand MyCommand
    {
        get { return this.myCommand; }
    }
    private void DoStuff() { ... }
}

这样做的优点是在RelayCommand实现中保留了额外的方法(如RaiseCanExecuteChanged),以便在视图模型中使用,但只向消费者公开一个ICommand实例。

我同意Krowi的观点,第一种方法更容易阅读。但我会把你的中继命令放在自己的类中,这样你就可以重用它:

public class RelayCommand : ICommand
{
    #region Fields
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;
    #endregion // Fields
    #region Constructors
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }
    #endregion
    #region ICommand Members
    [DebuggerStepThrough]
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    public void Execute(object parameter)
    {
        _execute(parameter);
    }
    #endregion
}

最新更新