# Easily control the executability of Commands using MVVM Source Generators

# Introduction

Welcome to the third part of my [mini-series](https://ewerspej.hashnode.dev/series/mvvm-goodness) about [**MVVM Source Generators**](https://learn.microsoft.com/dotnet/communitytoolkit/mvvm/generators/overview) for C# .NET and the awesomeness of the [**MVVM Community Toolkit**](https://learn.microsoft.com/windows/communitytoolkit/mvvm/introduction). So far, we have seen how we can save ourselves from writing too much boilerplate code when applying the MVVM pattern in .NET-based app technologies and UI frameworks.

In this part, I will give a short overview of yet another two amazing Source Generators which can be used to **control the executability of *Commands***. In classic MVVM without Source Generators this would usually be done using the *CanExecute* predicate of a *Command*, which enables or disables it. Even with Source Generators you can still achieve exactly the same behavior as you could with classic MVVM implementations.

In this scenario, we do not actually save as much boilerplate code as with the other Source Generators that I have explored previously. However, the attributes we will use are required in situations where you need to enable and disable *Commands* based on specific conditions, such as the validity of the *CommandParameter* or of properties in the *ViewModel* when using Source Generators.

> Special thanks to my colleague and friend [Marco Seraphin](https://www.linkedin.com/in/marco-seraphin-2785b61/) for pointing out that this topic would be a great addition to my blog. Marco has inspired this article and has helped by reviewing it.

Like in my previous posts on the topic, I am using a *.NET MAUI* project (check out the [**sample repository**](https://github.com/ewerspej/maui-samples)) to demonstrate the functionality, but since the MVVM Community Toolkit is independent from UI frameworks, the same things apply to technologies like *Windows Presentation Foundation* (WPF) and *Xamarin.Forms*.

# Setting

I am reusing the project from the [**sample repository**](https://github.com/ewerspej/maui-samples) with the address label printing functionality. In the [previous post](https://ewerspej.hashnode.dev/mvvm-source-generators-advanced-scenarios) I have added an `ActivityIndicator` as well as a `Stepper` control to the project to demonstrate *busyness* using `AsyncRelayCommand`.

If you remember from before, the `Button` to trigger the `PrintAddressCommand` was always enabled, but nothing would happen if the number of copies was set to 0. Since *Commands* can have a `CanExecute` predicate, which is used to determine whether they can be executed or not, they can also be used to enable and disable buttons automatically.

So, for the updated setting, I want the `Button` only to be enabled when the *Command* is actually executable, otherwise it should be disabled and thus be grayed out when the number of copies is 0 and the address is empty:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1675247214273/9d9adb36-5b7e-41d7-b4cf-9e65cc3645e7.png align="center")

Therefore, I have added a new method to the `AddressViewModel` which can be used as the `CanExecute` predicate for the `PrintAddressCommand`:

```csharp
private bool CanPrint(string address) => Copies > 0 && !string.IsNullOrWhiteSpace(address);
```

This method checks if the argument that is passed into the *Command* is valid *(for simplicity, I am only checking for null and whitespaces or an empty string)* and if the number of copies to print is larger than 0.

When using the `CanPrint()` method as a predicate in the classic version of the `AddressViewModel`, the *Command* would then look like follows:

```csharp
private IAsyncRelayCommand _printAddressCommand;
public IAsyncRelayCommand PrintAddressCommand => _printAddressCommand ??= new AsyncRelayCommand<string>(PrintAddressAsync, canExecute: CanPrint);
```

Our `Button` in the XAML of our UI has also been updated to pass in the address as a *CommandParameter*:

```xml
<Button
    Command="{Binding PrintAddressCommand}"
    CommandParameter="{Binding FullAddress}"
    Text="Print Address" />
```

In this case, I am simply passing in the `FullAddress` property.

> **Note:** I have used the `FullAddress` property as a CommandParameter only for demonstration purposes. Since it's a property of the same ViewModel as the Command, I could have also directly accessed the property inside of the `CanPrint()` method instead of passing it in.

This already suffices to enable and disable the `Button` automatically, we ***cannot*** use the `IsEnabled` property of the `Button` in this setting and it's also not required.

> **Important:** In .NET MAUI and Xamarin.Forms, you should not use the IsEnabled property when using Commands, because it will automatically be overridden when binding to a Command. Find more information in the official [documentation](https://learn.microsoft.com/dotnet/maui/fundamentals/data-binding/commanding#icommands).

# Controlling Executability

Generally, the `CanExecute` predicate is only evaluated by the *Command* during instantiation or when an argument is passed to the *Command* via the *CommandParameter* property. In the latter case, the `CanExecute` predicate is evaluated each time that the *CommandParameter*, which our `Button` binds to, changes.

> **Important:** The method which is used for the predicate must return a `bool` and optionally may have exactly one input parameter which must correspond to the CommandParameter.

However, there are also scenarios in which the predicate depends on properties which are not passed in as an argument of the *CommandParameter*. In these situations, we need to manually inform the *Command* that something has changed and that its executability should be re-evaluated.

Let's explore how this is usually done using classic MVVM in .NET and then let's have a look at how this can be done using the previously introduced Source Generators.

## Using Classic MVVM

When using the classic MVVM approach to update the *Command* and re-evaluate its executability, the ViewModel *(stripped down to the relevant bits only)* would look as follows:

```csharp
private IAsyncRelayCommand _printAddressCommand;
public IAsyncRelayCommand PrintAddressCommand => _printAddressCommand ??= new AsyncRelayCommand<string>(PrintAddressAsync, canExecute: CanPrint);

private async Task PrintAddressAsync(string address)
{
    await Task.Delay(TimeSpan.FromSeconds(2));
    OnPrintAddress?.Invoke(address);
}

private bool CanPrint(string address) => Copies > 0 && !string.IsNullOrWhiteSpace(address);

private int _copies;
public int Copies
{
    get => _copies;
    set
    {
        if (value == _copies)
        {
            return;
        }

        OnPropertyChanging();
        _copies = value;
        OnPropertyChanged();

        PrintAddressCommand.NotifyCanExecuteChanged();
    }
}
```

Here, we pass the `CanPrint()` method, which exists in both versions equally, as an argument to the Command's `canExecute` parameter. The *CanExecute* predicate of the *Command* is evaluated each time when the *CommandParameter*, the `address` string, changes and it is also re-evaluated when the `Copies` property changes, because the *Command* gets notified by calling `NotifyCanExecuteChanged()` on it.

This already isn't much code thanks to the `NotifyCanExecuteChanged()` method that the `IRelayCommand` interface provides.

## Using MVVM Source Generators

Since the Source Generators largely take care of the implementation of properties and commands for us, we need a way to pass in the `canExecute` parameter to the *Command*. We also need a way to trigger an update on the *Command* to re-evaluate its executability. The first attribute might look familiar from prior usage and the second one also has similarities with another attribute that we've already explored before. It's time to look at `[RelayCommand]` again and then we'll do a short dive into `[NotifyCanExecuteChangedFor]`.

### Revisiting \[RelayCommand\]

In order to configure and update the executability of a *Command* via the `canExecute` parameter, the `[RelayCommand]` attribute comes with an optional property of type `string?`, which conveniently is called `CanExecute` and which is used to provide the name of the method that is used to evaluate the executability of the *Command*:

```csharp
[RelayCommand(CanExecute = nameof(CanPrint))]
private async Task PrintAddressAsync(string address) { /* ... */ }
```

The main difference compared to the classic approach is that we pass in the *name* of the method to the Source Generator instead of the method itself.

Under the hood, the Source Generator actually generates a *Command* which looks remarkably similar to the one from the ViewModel without Source Generators:

```csharp
partial class AddressViewModelSourceGen
{
    /// <summary>The backing field for <see cref="PrintAddressCommand"/>.</summary>
    [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator", "8.1.0.0")]
    private global::CommunityToolkit.Mvvm.Input.AsyncRelayCommand<string>? printAddressCommand;
    /// <summary>Gets an <see cref="global::CommunityToolkit.Mvvm.Input.IAsyncRelayCommand{T}"/> instance wrapping <see cref="PrintAddressAsync"/>.</summary>
    [global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator", "8.1.0.0")]
    [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
    public global::CommunityToolkit.Mvvm.Input.IAsyncRelayCommand<string> PrintAddressCommand => printAddressCommand ??= new global::CommunityToolkit.Mvvm.Input.AsyncRelayCommand<string>(new global::System.Func<string, global::System.Threading.Tasks.Task>(PrintAddressAsync), CanPrint);
}
```

As we can see, the name of the method is simply used by the Source Generator to insert it as text into the generated code file and serves as the argument for the `canExecute` parameter *(all the way at the end, where it says* `CanPrint`*)*.

Since the generated *Command* is of type `AsyncRelayCommand<string>`, any arguments passed into a *Command* as a *CommandParameter* are forwarded to the `PrintAddressAsync()` and `CanPrint()` methods respectively.

With this in place, the executability of the *Command* will be re-evaluated every time that the *CommandParameter* of our `Button` changes. But how do we notify the *Command* about changes to the `Copies` property from the ViewModel?

### Introducing \[NotifyCanExecuteChangedFor\]

When a property changes and we want to notify subscribers that another property, *e.g. a getter-only one*, likely has changed as well, we can use the `[NotifyPropertyChangedFor]` attribute when using Source Generators. Fortunately, a similar attribute exists for commands: `[NotifyCanExecuteChangedFor]`, which also works in the same fashion.

The `[NotifyCanExecuteChangedFor]` attribute is used to decorate any property which may be required to determine the executability of a *Command* and takes the name of the *Command* as an argument:

```csharp
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(PrintAddressCommand))]
private int _copies;
```

This is all we need to do in order to trigger a re-evaluation of the `CanExecute` predicate attached to the `PrintAddressCommand`. Every time that the auto-generated `Copies` property gets updated, the re-evaluation takes place.

Under the hood, this also looks highly familiar: At the end of the auto-generated property's setter, the `NotifyCanExecuteChanged()` method is called on the auto-generated `PrintAddressCommand`:

```csharp
/// <inheritdoc cref="_copies"/>
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "8.1.0.0")]
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
public int Copies
{
    get => _copies;
    set
    {
        if (!global::System.Collections.Generic.EqualityComparer<int>.Default.Equals(_copies, value))
        {
            OnCopiesChanging(value);
            OnPropertyChanging(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangingArgs.Copies);
            _copies = value;
            OnCopiesChanged(value);
            OnPropertyChanged(global::CommunityToolkit.Mvvm.ComponentModel.__Internals.__KnownINotifyPropertyChangedArgs.Copies);
            PrintAddressCommand.NotifyCanExecuteChanged();
        }
    }
}
```

This is exactly what I have also done in the ViewModel that does not use the Source Generators of the MVVM Community Toolkit: First, the equality comparison of the *backing field* and the new *value* takes place, followed by the notification that the property *is about to* change, then the backing field gets updated, which is then followed by the notification that the property *has* *just* changed and finally, the `CanExecuteChanged` event of the `PrintAddressCommand` is raised by calling `NotifyCanExecuteChanged()`.

### ViewModel with Source Generators

The completed version of the ViewModel *(again stripped down to the relevant bits only)* using Source Generators looks as follows:

```csharp
[RelayCommand(CanExecute = nameof(CanPrint))]
private async Task PrintAddressAsync(string address)
{
    await Task.Delay(TimeSpan.FromSeconds(2));
    OnPrintAddress?.Invoke(address);
}

private bool CanPrint(string address) => Copies > 0 && !string.IsNullOrWhiteSpace(address);

[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(PrintAddressCommand))]
private int _copies;
```

Amazing, this looks (c)lean and beautiful. My developer heart is happy - again 💖.

# Running the sample

In both versions, we can now run the sample app and see that the `Button` is only enabled when the address is not empty and at least one copy is set to be printed:

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1675247242167/6e224685-13f6-4dd5-8246-deaa913805b1.png align="center")

Perfect! 💪 There's no need to do without the functionality that *CanExecute* provides when using auto-generated commands, because the MVVM Source Generators have us covered here, as well.

# Conclusions and next steps

Evaluating the executability of commands is still possible like before even with Source Generators. We can still write exactly the same kind of logic like we did before while saving loads of valuable time and tremendously reducing the risk of bugs, especially when dealing with a multitude of different properties and commands.

Source Generators can help you with decreasing the amount of boilerplate code and make ViewModels much more legible and comprehensible, *provided you have a basic understanding of the MVVM pattern.* At the same time, you do not have to live without your favorite MVVM features and interfaces, since they are all compatible and complementary, with and without using Source Generators - mix and match, if you will.

In my humble opinion, this is all relatively straightforward, as long as you have a working understanding of the MVVM pattern and its implementation in .NET. I hope that you learned something again from this article.

Last but not least, my friend and colleague Marco has his [own sample](https://github.com/marcoseraphin/MVVMToolkitMAUISample) repository on GitHub with another example using the *CanExecute* predicate, check it out if you like.

If you enjoyed this blog post, then follow me on [**LinkedIn**](https://www.linkedin.com/in/jewerspeters), subscribe to this [**blog**](https://hashnode.com/@ewerspej) and star the [**GitHub** **repository**](https://github.com/ewerspej/maui-samples) for this post so you don't miss out on any future posts and developments.
