RelayCommand: CanExecute no longer automatically checked on Execute #240
-
I'm migrating from MvvmLight to MVVM Toolkit. I was wondering what the explanation is for not automatically calling In MvvmLight this was the case but as indicated by the test I was wondering why this change. What was considering when not taking over such a "obvious" behaviour? Further why is this not mentioned in the Migration Guide? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 7 replies
-
We decided not to do this as it was technically against the We should mention that in the docs too, absolutely. We just haven't had time to update them just yet 🙂 |
Beta Was this translation helpful? Give feedback.
-
I agree with you on all the points. Yet I'd like to point out that the documentation of You are therefore relying on an implementation detail to justify this change. I do understand that no current (and probably future framework) will ever deviate from this. That's why I'd like to know whether there would be an interest in a Another benefit is that we could have a version that only passes non-nullable values to |
Beta Was this translation helpful? Give feedback.
-
I'm sorry to pick this up but I have seen something strange. The disassembly of the source code with VS showed me this: Please notice that it is a very recent release and yet the #region Assembly Microsoft.Toolkit.Mvvm, Version=7.1.0.0, Culture=neutral, PublicKeyToken=4aff67a105548ee2
// C:\data\Silt4\src\App\Packages\microsoft.toolkit.mvvm\7.1.2\lib\netstandard2.0\Microsoft.Toolkit.Mvvm.dll
// Decompiled with ICSharpCode.Decompiler 6.1.0.5902
#endregion
using System;
using System.Runtime.CompilerServices;
using System.Windows.Input;
namespace Microsoft.Toolkit.Mvvm.Input
{
//
// Summary:
// A command whose sole purpose is to relay its functionality to other objects by
// invoking delegates. The default return value for the Microsoft.Toolkit.Mvvm.Input.RelayCommand.CanExecute(System.Object)
// method is true. This type does not allow you to accept command parameters in
// the Microsoft.Toolkit.Mvvm.Input.RelayCommand.Execute(System.Object) and Microsoft.Toolkit.Mvvm.Input.RelayCommand.CanExecute(System.Object)
// callback methods.
public sealed class RelayCommand : IRelayCommand, ICommand
{
//
// Summary:
// The System.Action to invoke when Microsoft.Toolkit.Mvvm.Input.RelayCommand.Execute(System.Object)
// is used.
private readonly Action execute;
//
// Summary:
// The optional action to invoke when Microsoft.Toolkit.Mvvm.Input.RelayCommand.CanExecute(System.Object)
// is used.
private readonly Func<bool>? canExecute;
public event EventHandler? CanExecuteChanged;
//
// Summary:
// Initializes a new instance of the Microsoft.Toolkit.Mvvm.Input.RelayCommand class
// that can always execute.
//
// Parameters:
// execute:
// The execution logic.
[NullableContext(1)]
public RelayCommand(Action execute)
{
this.execute = execute;
}
//
// Summary:
// Initializes a new instance of the Microsoft.Toolkit.Mvvm.Input.RelayCommand class.
//
// Parameters:
// execute:
// The execution logic.
//
// canExecute:
// The execution status logic.
[NullableContext(1)]
public RelayCommand(Action execute, Func<bool> canExecute)
{
this.execute = execute;
this.canExecute = canExecute;
}
//
// Summary:
// Notifies that the System.Windows.Input.ICommand.CanExecute(System.Object) property
// has changed.
public void NotifyCanExecuteChanged()
{
this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool CanExecute(object? parameter)
{
return canExecute?.Invoke() ?? true;
}
public void Execute(object? parameter)
{
if (CanExecute(parameter))
{
execute();
}
}
}
}
// Rest omitted. |
Beta Was this translation helpful? Give feedback.
We decided not to do this as it was technically against the
ICommand
interface (see here). The docs forExecute
say that that method will execute the command action, they don't mention anything about it doing the "can execute" checks again. It's whoever's using the command that's responsible for callingCanExecute
first, or it's the UI framework binding to the command that's responsible for subscribing toCanExecuteChanged
and then callingCanExecute
to update theIsEnabled
state for whatever button or control is bound to the command. This is also what the command implementation from WPF is doing. What was in MvvmLight was not really following theICommand
contract, so we rectified that i…