Example #1
0
        public async Task Test_AsyncRelayCommand_WithCancellation()
        {
            TaskCompletionSource <object> tcs = new TaskCompletionSource <object>();

            var command = new AsyncRelayCommand(token => tcs.Task);

            Assert.IsTrue(command.CanExecute(null));
            Assert.IsTrue(command.CanExecute(new object()));

            Assert.IsTrue(command.CanBeCanceled);
            Assert.IsFalse(command.IsCancellationRequested);

            command.Execute(null);

            Assert.IsFalse(command.IsCancellationRequested);

            command.Cancel();

            Assert.IsTrue(command.IsCancellationRequested);

            tcs.SetResult(null);

            await command.ExecutionTask !;

            Assert.IsTrue(command.IsCancellationRequested);
        }
        public async Task Test_AsyncRelayCommand_WithCancellation()
        {
            TaskCompletionSource <object> tcs = new TaskCompletionSource <object>();

            // We need to test the cancellation support here, so we use the overload with an input
            // parameter, which is a cancellation token. The token is the one that is internally managed
            // by the AsyncRelayCommand instance, and canceled when using IAsyncRelayCommand.Cancel().
            var command = new AsyncRelayCommand(token => tcs.Task);

            List <PropertyChangedEventArgs> args = new List <PropertyChangedEventArgs>();

            command.PropertyChanged += (s, e) => args.Add(e);

            // We have no canExecute parameter, so the command can always be invoked
            Assert.IsTrue(command.CanExecute(null));
            Assert.IsTrue(command.CanExecute(new object()));

            // The command isn't running, so it can't be canceled yet
            Assert.IsFalse(command.CanBeCanceled);
            Assert.IsFalse(command.IsCancellationRequested);

            // Start the command, which will return the token from our task completion source.
            // We can use that to easily keep the command running while we do our tests, and then
            // stop the processing by completing the source when we need (see below).
            command.Execute(null);

            // The command is running, so it can be canceled, as we used the token overload
            Assert.IsTrue(command.CanBeCanceled);
            Assert.IsFalse(command.IsCancellationRequested);

            // Validate the various event args for all the properties that were updated when executing the command
            Assert.AreEqual(args.Count, 4);
            Assert.AreEqual(args[0].PropertyName, nameof(IAsyncRelayCommand.IsCancellationRequested));
            Assert.AreEqual(args[1].PropertyName, nameof(IAsyncRelayCommand.ExecutionTask));
            Assert.AreEqual(args[2].PropertyName, nameof(IAsyncRelayCommand.IsRunning));
            Assert.AreEqual(args[3].PropertyName, nameof(IAsyncRelayCommand.CanBeCanceled));

            command.Cancel();

            // Verify that these two properties raised notifications correctly when canceling the command too.
            // We need to ensure all command properties support notifications so that users can bind to them.
            Assert.AreEqual(args.Count, 6);
            Assert.AreEqual(args[4].PropertyName, nameof(IAsyncRelayCommand.IsCancellationRequested));
            Assert.AreEqual(args[5].PropertyName, nameof(IAsyncRelayCommand.CanBeCanceled));

            Assert.IsTrue(command.IsCancellationRequested);

            // Complete the source, which will mark the command as completed too (as it returned the same task)
            tcs.SetResult(null);

            await command.ExecutionTask !;

            // Verify that the command can no longer be canceled, and that the cancellation is
            // instead still true, as that's reset when executing a command and not on completion.
            Assert.IsFalse(command.CanBeCanceled);
            Assert.IsTrue(command.IsCancellationRequested);
        }