问题描述
对我来说,学习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更改可以自动执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!