简体   繁体   English

RelayCommand最佳做法

[英]RelayCommand best practice

I'm working with RelayCommands (they are in a separate class) for about a month now and I got the feeling they're kind of clunky when declaring them. 我工作RelayCommands (他们是在一个单独的类),现在约一个月,我得到了他们宣布他们的时候那种笨重是的感觉。 Below I have 3 ways I can think of how I can declare a RelayCommand . 下面,我有3种方法可以考虑如何声明RelayCommand

In a first case I declare my ICommand and then when the ViewModel is loading I construct my RelayCommand that points to a method in my code. 在第一种情况下,我宣布我ICommand ,然后在视图模型加载我建立我的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;
    }
}

A second method is to do everything at once. 第二种方法是立即执行所有操作。

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

Now, I'm planning to write an application with quite some Commands in a certain ViewModel. 现在,我打算在某个ViewModel中编写带有很多Commands的应用程序。 I also can't split the ViewModel in smaller ViewModels because all the controls have to work together. 我也无法将ViewModel拆分为较小的ViewModel,因为所有controls必须一起工作。

So my questions are: 所以我的问题是:

  1. What is the best approach to declaring and constructing ICommands ? 声明和构造ICommands的最佳方法是什么? Is it one of my approaches or is there an easier way? 这是我的方法之一还是有更简单的方法?
  2. How hard is it to maintain the overview with each approach considering there are over 50 ICommands in a single ViewModel. 考虑到单个ViewModel中有50多个ICommands ,使用每种方法维护概述的难度有多大。
  3. I'm hoping to release my application on both Windows 7, 8 and 10 in the future. 我希望将来能在Windows 7、8和10上发布我的应用程序。 Are there any limitations to RelayCommands I have to take in account if I'm only using .NET4.5? 如果仅使用.NET4.5,我必须考虑的RelayCommands是否有任何限制?
  4. Besides RelayCommands I also found this project: Caliburn-Micro . 除了RelayCommands之外,我还找到了这个项目: Caliburn-Micro It allows you to do something like the code below. 它允许您执行类似以下代码的操作。 Does anyone have an idea how good this works performance wise in comparison to RelayCommands ? 有没有人知道与RelayCommands相比,这在性能上有多好? This is just an extra question and not required to be answered to have a post marked as an answer. 这只是一个额外的问题,在帖子被标记为答案时不需要回答。

Xaml (View) 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)
{
    ...
}

Refer below answers. 请参考以下答案。

  1. What is the best approach to declaring and constructing ICommands? 声明和构造ICommands的最佳方法是什么? Is it one of my approaches or is there an easier way? 这是我的方法之一还是有更简单的方法? Ans:You can take combined approach. 回答:您可以采取综合方法。 If your execute method is very minimal, you can use RelayCommnd otherwise you can implement your own ICommand in a separate class. 如果您的execute方法非常少,则可以使用RelayCommnd,否则可以在单独的类中实现自己的ICommand。 This will improve readability of your viewmodel as well as modularity of your code. 这将提高您的视图模型的可读性以及代码的模块化。
  2. How hard is it to maintain the overview with each approach considering there are over 50 ICommands in a single ViewModel. 考虑到单个ViewModel中有50多个ICommand,使用每种方法维护概述的难度有多大。 Ans: Cover in Ans 1 Ans:Ans 1中的封面
  3. I'm hoping to release my application on both Windows 7, 8 and 10 in the future. 我希望将来能在Windows 7、8和10上发布我的应用程序。 Are there any limitations to RelayCommands I have to take in account if I'm only using .NET4.5? 如果仅使用.NET4.5,我必须考虑的RelayCommands是否有任何限制? Ans: I am not seeing any limitation in Windows 7 or 8 but not sure about Windows 10. 回答:我在Windows 7或8中没有看到任何限制,但是不确定Windows 10。
  4. Besides RelayCommands I also found this project: Caliburn-Micro. 除了RelayCommands,我还找到了这个项目:Caliburn-Micro。 It allows you to do something like the code below. 它允许您执行类似以下代码的操作。 Does anyone have an idea how good this works performance wise in comparison to RelayCommands? 有没有人知道与RelayCommands相比,这在性能上有多好? This is just an extra question and not required to be answered to have a post marked as an answer. 这只是一个额外的问题,在帖子被标记为答案时不需要回答。 Ans: I am not sure about source code of RelayCommands in Caliburn-Micro. 回答:我不确定Caliburn-Micro中RelayCommands的源代码。 But if it using CommandManager to achieve the CanExecute functionality. 但是如果使用CommandManager来实现CanExecute功能。 Then command manager will get triggered for all the user inputs change and hence that will cause performance issues if have some heavy logic in the CanExecute method. 然后,对于所有用户输入的更改,命令管理器将被触发,因此,如果CanExecute方法中包含大量逻辑,则将导致性能问题。 Refer Are there any performance implications with CanExecuteCommand? 请参阅CanExecuteCommand是否会对性能产生影响?

Here's the pattern that I prefer, which is basically a variation of method 1: 这是我更喜欢的模式,基本上是方法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() { ... }
}

This has the advantage of keeping extra methods on your RelayCommand implementation (like RaiseCanExecuteChanged ) around for use from your view model, but exposes only an ICommand instance to consumers. 这样做的好处是,可以在您的RelayCommand实现上保留其他方法(例如RaiseCanExecuteChanged ),以供您在视图模型中使用,但仅向使用者公开ICommand实例。

I agree with Krowi, the first approach is much easier to read. 我同意Krowi的观点,第一种方法更容易阅读。 But I would put your relay command into its own class so you can re-use it: 但是我会将您的Relay命令放入其自己的类中,以便您可以重新使用它:

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM