Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 19 additions & 24 deletions CommunityToolkit.Mvvm/Input/AsyncRelayCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -280,36 +280,31 @@ public void Execute(object? parameter)
/// <inheritdoc/>
public Task ExecuteAsync(object? parameter)
{
if (CanExecute(parameter))
{
Task executionTask;
Task executionTask;

if (this.execute is not null)
{
// Non cancelable command delegate
executionTask = ExecutionTask = this.execute();
}
else
{
// Cancel the previous operation, if one is pending
this.cancellationTokenSource?.Cancel();

CancellationTokenSource cancellationTokenSource = this.cancellationTokenSource = new();
if (this.execute is not null)
{
// Non cancelable command delegate
executionTask = ExecutionTask = this.execute();
}
else
{
// Cancel the previous operation, if one is pending
this.cancellationTokenSource?.Cancel();

// Invoke the cancelable command delegate with a new linked token
executionTask = ExecutionTask = this.cancelableExecute!(cancellationTokenSource.Token);
}
CancellationTokenSource cancellationTokenSource = this.cancellationTokenSource = new();

// If concurrent executions are disabled, notify the can execute change as well
if (!this.allowConcurrentExecutions)
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
// Invoke the cancelable command delegate with a new linked token
executionTask = ExecutionTask = this.cancelableExecute!(cancellationTokenSource.Token);
}

return executionTask;
// If concurrent executions are disabled, notify the can execute change as well
if (!this.allowConcurrentExecutions)
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}

return Task.CompletedTask;
return executionTask;
}

/// <inheritdoc/>
Expand Down
44 changes: 19 additions & 25 deletions CommunityToolkit.Mvvm/Input/AsyncRelayCommand{T}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -282,37 +282,31 @@ public void Execute(object? parameter)
/// <inheritdoc/>
public Task ExecuteAsync(T? parameter)
{
if (CanExecute(parameter))
{
Task executionTask;
Task executionTask;


if (this.execute is not null)
{
// Non cancelable command delegate
executionTask = ExecutionTask = this.execute(parameter);
}
else
{
// Cancel the previous operation, if one is pending
this.cancellationTokenSource?.Cancel();

CancellationTokenSource cancellationTokenSource = this.cancellationTokenSource = new();
if (this.execute is not null)
{
// Non cancelable command delegate
executionTask = ExecutionTask = this.execute(parameter);
}
else
{
// Cancel the previous operation, if one is pending
this.cancellationTokenSource?.Cancel();

// Invoke the cancelable command delegate with a new linked token
executionTask = ExecutionTask = this.cancelableExecute!(parameter, cancellationTokenSource.Token);
}
CancellationTokenSource cancellationTokenSource = this.cancellationTokenSource = new();

// If concurrent executions are disabled, notify the can execute change as well
if (!this.allowConcurrentExecutions)
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
// Invoke the cancelable command delegate with a new linked token
executionTask = ExecutionTask = this.cancelableExecute!(parameter, cancellationTokenSource.Token);
}

return executionTask;
// If concurrent executions are disabled, notify the can execute change as well
if (!this.allowConcurrentExecutions)
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}

return Task.CompletedTask;
return executionTask;
}

/// <inheritdoc/>
Expand Down
5 changes: 1 addition & 4 deletions CommunityToolkit.Mvvm/Input/RelayCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,6 @@ public bool CanExecute(object? parameter)
/// <inheritdoc/>
public void Execute(object? parameter)
{
if (CanExecute(parameter))
{
this.execute();
}
this.execute();
}
}
5 changes: 1 addition & 4 deletions CommunityToolkit.Mvvm/Input/RelayCommand{T}.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,7 @@ public bool CanExecute(object? parameter)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Execute(T? parameter)
{
if (CanExecute(parameter))
{
this.execute(parameter);
}
this.execute(parameter);
}

/// <inheritdoc/>
Expand Down
11 changes: 4 additions & 7 deletions tests/CommunityToolkit.Mvvm.UnitTests/Test_AsyncRelayCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,13 @@ public void Test_AsyncRelayCommand_WithCanExecuteFunctionFalse()

command.Execute(null);

Assert.AreEqual(ticks, 0);
// It is the caller's responsibility to ensure that CanExecute is true
// before calling Execute. This check verifies the logic is still called.
Assert.AreEqual(ticks, 1);

command.Execute(new object());

Assert.AreEqual(ticks, 0);
Assert.AreEqual(ticks, 2);
}

[TestMethod]
Expand Down Expand Up @@ -289,11 +291,6 @@ private static async Task Test_AsyncRelayCommand_AllowConcurrentExecutions_TestL
Assert.IsFalse(command.CanBeCanceled);
Assert.IsFalse(command.IsCancellationRequested);

Task newTask = command.ExecuteAsync(null);

// Execution failed, so a completed task was returned
Assert.AreSame(newTask, Task.CompletedTask);

tcs.SetResult(null);

await task;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,12 @@ public void Test_AsyncRelayCommandOfT_WithCanExecuteFunctionFalse()

command.Execute("2");

Assert.AreEqual(ticks, 0);
// Like in the RelayCommand test, ensure Execute is unconditionally invoked
Assert.AreEqual(ticks, 2);

command.Execute("42");

Assert.AreEqual(ticks, 0);
Assert.AreEqual(ticks, 42);
}

[TestMethod]
Expand Down Expand Up @@ -231,11 +232,6 @@ private static async Task Test_AsyncRelayCommandOfT_AllowConcurrentExecutions_Te
Assert.IsFalse(command.CanBeCanceled);
Assert.IsFalse(command.IsCancellationRequested);

Task newTask = command.ExecuteAsync(null);

// Execution failed, so a completed task was returned
Assert.AreSame(newTask, Task.CompletedTask);

tcs.SetResult(null);

await task;
Expand Down
Loading