首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RelayCommand变更canExecute自动

RelayCommand变更canExecute自动
EN

Stack Overflow用户
提问于 2018-06-19 12:02:38
回答 1查看 1.6K关注 0票数 1

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

所以我想出了一个RelayCommand类:

中继命令类

代码语言:javascript
复制
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时显示错误消息。

代码语言:javascript
复制
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。

代码语言:javascript
复制
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是这样的:

  • 1-点击按钮
  • 第二- canExecute = false (等待处理完成)
  • 第三- canExecute =真
  • 第四-按钮可以再次执行。

这样你就不能垃圾邮件按钮点击和崩溃应用程序,例如,有人使用SpeedClicker,并点击1.000.000次,每秒钟左右。

EN

回答 1

Stack Overflow用户

发布于 2018-06-19 13:47:59

在创建命令时,必须将一些can-execute逻辑传递给命令:

代码语言:javascript
复制
public ViewModel()
{
    MyCommand = new RelayCommand(MyCommandMethod, MyCanExecutePredicate);
}

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

示例:如果您希望一次只执行一条命令,您可以根据以下几条思路得出如下结果:

代码语言:javascript
复制
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;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50927967

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档