本文介绍了RelayCommand更改可以自动执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对我来说,学习MVVM的当前步骤是RelayCommand.

The current step of learning MVVM is RelayCommand for me.

所以我想出了这个RelayCommand类:

So i came up with this RelayCommand class:

中继命令类

public class RelayCommand : ICommand
{
    private readonly Action<object> _execute;
    private readonly Func<object, bool> _canExecute;

    public RelayCommand(Action<object> execute) : this(execute, null)
    {

    }
    public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
    {
        _execute = execute ?? throw new ArgumentNullException(nameof(execute));
        _canExecute = canExecute ?? (x => true);
    }



    public bool CanExecute(object parameter)
    {
        return _canExecute(parameter);
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add => CommandManager.RequerySuggested += value;
        remove => CommandManager.RequerySuggested -= value;
    }

    public void Refresh()
    {
        CommandManager.InvalidateRequerySuggested();
    }
}

查看隐藏代码

要测试CanExecute是对还是假,我创建了一个Click事件,如果CanExecute == true则调用Command或CanExecute == false时显示错误消息.

To test if CanExecute is true or false, I created a Click Event which is calling the Command if CanExecute == true or Show an Error Message when CanExecute == false.

if (sender is Button button)
{
    if (_viewModel.MyCommand.CanExecute(button.Tag)) // Also testet to set this parameter `null`
        _viewModel.MyCommand.Execute(button.Tag);
    else
        ErrorMessage.Error("CanExecute = false");
}

ViewModel

在ViewModel中,我创建了Command,并添加了Thread.Sleep()以使canExecute有时间显示Code-Behind中的错误消息.

In my ViewModel I created the Command and added a Thread.Sleep() to have time that canExecute can show me the ErrorMessage from the Code-Behind.

public ICommand MyCommand { get; set; }
public ViewModel()
{
    MyCommand = new RelayCommand(MyCommandMethod);
}

public async void MyCommandMethod(object obj)
{
    await Task.Run(() =>
    {
        Thread.Sleep(5000);
        ErrorMessage.Error(obj as string);
    });

}

现在的问题是,例如,如果我单击按钮5次,则使用MyCommandMetod() 5次.因此CanExecute将永远不会改变.

The Problem now is, that if I click the Button 5 times for example, that MyCommandMetod() is used 5 times. So CanExecute will never change.

但是为什么它没有变化?

But why isn't it changing?

我这样理解RelayCommand:

I understand RelayCommand as this:

  • 第一个-单击按钮
  • 2nd-canExecute = false(等待过程完成)
  • 第三-canExecute = true
  • 第4个-可以再次执行按钮.

例如,如果有人使用SpeedClicker并每秒点击1.000.000次,那么您就不会发送垃圾邮件.Button会单击并使应用程序崩溃.

So that u can't spam Button clicks and crash the application if for example someone use SpeedClicker and clicks 1.000.000 times a seconds or so.

推荐答案

创建该命令时,您必须将一些can-execute-logic传递给该命令:

You have to pass some can-execute-logic to the command when creating it:

public ViewModel()
{
    MyCommand = new RelayCommand(MyCommandMethod, MyCanExecutePredicate);
}

private bool MyCanExecutePredicate( object commandParameter )
{
    // TODO: decide whether or not MyCommandMethod is allowed to execute right now
}

示例:如果您一次只允许执行一个命令,则可以根据以下内容提出一些建议:

Example: if you want to allow only one command execution at a time, you could come up with something along these lines:

public async void MyCommandMethod(object obj)
{
    _myCanExecute = false;
    MyCommand.Refresh();
    await Task.Run(() =>
    {
        Thread.Sleep(5000);
        ErrorMessage.Error(obj as string);
    });
    _myCanExecute = true;
    MyCommand.Refresh();
}

private bool MyCanExecutePredicate( object commandParameter )
{
    return _myCanExecute;
}

这篇关于RelayCommand更改可以自动执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 17:46
查看更多