对于我来说,学习MVVM的当前步骤是RelayCommand。
所以我想出了一个RelayCommand类:
中继命令类
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命令,或者在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中,我创建了命令,并添加了一个Thread.Sleep(),以便canExecute可以从Code-Behind向我展示ErrorMessage。
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永远不会改变。
但为什么不改变呢?
我理解RelayCommand是这样的:
这样你就不能垃圾邮件按钮点击和崩溃应用程序,例如,有人使用SpeedClicker,并点击1.000.000次,每秒钟左右。
发布于 2018-06-19 13:47:59
在创建命令时,必须将一些can-execute逻辑传递给命令:
public ViewModel()
{
MyCommand = new RelayCommand(MyCommandMethod, MyCanExecutePredicate);
}
private bool MyCanExecutePredicate( object commandParameter )
{
// TODO: decide whether or not MyCommandMethod is allowed to execute right now
}示例:如果您希望一次只执行一条命令,您可以根据以下几条思路得出如下结果:
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;
}https://stackoverflow.com/questions/50927967
复制相似问题