Relay Command can execute and a Task

后端 未结 5 2083
故里飘歌
故里飘歌 2020-12-14 04:13

i want to start a task when a relay command is called, however i want to disable the button as long as that task is running

take this example

private         


        
5条回答
  •  -上瘾入骨i
    2020-12-14 04:45

    So your solution to use RelayCommand almost works. The problem is that the UI won't immediately update after the task finishes running. This is because something needs to trigger the ICommand's CanExecuteChanged event in order for the UI to properly update.

    One way to solve this problem is by creating a new kind of ICommand. For example:

      class AsyncRelayCommand : ICommand
      {
        private Func _action;
        private Task _task;
    
        public AsyncRelayCommand(Func action)
        {
          _action = action;
        }
    
        public bool CanExecute(object parameter)
        {
          return _task == null || _task.IsCompleted;
        }
    
        public event EventHandler CanExecuteChanged;
    
        public async void Execute(object parameter)
        {
          _task = _action(parameter);
          OnCanExecuteChanged();
          await _task;
          OnCanExecuteChanged();
        }
    
        private void OnCanExecuteChanged()
        {
          var handler = this.CanExecuteChanged;
          if (handler != null)
            handler(this, EventArgs.Empty);
        }
      }
    

    Now your view model can do something like the following

    private ICommand myCommand;
    public ICommand MyCommand
    {
      get { return myCommand ?? (myCommand = new AsyncRelayCommand(p => Task.Factory.StartNew(doStuff))); }
    }
    
    private void doStuff()
    {
      System.Threading.Thread.Sleep(5000);
    }
    

    Or you could make your doStuff function an "async" function like so

    private ICommand myCommand2;
    public ICommand MyCommand2
    {
      get { return myCommand2 ?? (myCommand2 = new AsyncRelayCommand(p => doStuff2())); }
    }
    private async Task doStuff2()
    {
      await Task.Delay(5000);
    }
    

提交回复
热议问题