Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set RelayCommand's CanExecute to false if any other command in the viewmodel is executing #826

Open
BurkusCat opened this issue Jan 10, 2024 · 0 comments
Labels
feature request 📬 A request for new changes to improve functionality

Comments

@BurkusCat
Copy link

BurkusCat commented Jan 10, 2024

Overview

RelayCommand's automatically disables concurrent execution which is great. They also offer the option for a property to have the attribute [NotifyCanExecuteChangedFor(nameof(GreetUserCommand))] and the command to have [RelayCommand(CanExecute = nameof(CanGreetUser))] so that the command decides if it can execute based on a property changing.

What isn't possible (or at least would require a lot of boilerplate code) is: disabling commands while other commands are running. For example, say I have a few commands in a .NET MAUI application that open pages. Disabling concurrent execution prevents a user from repeatedly pressing one button to open multiple pages, but if they press the other buttons then it is possible several pages will open causing unpredictable bugs.

In the past, I've used an IsBusy property on base view models where commands have disabled if IsBusy is set to true. This maybe isn't necessary to achieve the goal, so maybe something else like allowing commands to be grouped together where they aren't allowed to execute if another command in the group is executing.

API breakdown

// has a downside where it can only disables execution with every other command that is running
[RelayCommand(DisableConcurrentExecutionsWithOtherCommands = true)]
private void GreetUser(User? user)
{
    Console.WriteLine($"Hello {user!.Name}!");
}
// commands could be grouped in some way so that commands in a group never execute at the same time as each other
[RelayCommand(DisableConcurrentExecutionsWithOtherCommands(nameof(ArbitraryUniqueGroupIdentifierA)))]
private void GreetUser(User? user)
{
    Console.WriteLine($"Hello {user!.Name}!");
}


[RelayCommand(DisableConcurrentExecutionsWithOtherCommands(nameof(ArbitraryUniqueGroupIdentifierB)))]
private void SomeOther(User? user)
{
    Console.WriteLine($"Hello {user!.Name}!");
}
// if you didn't need to call "[NotifyCanExecuteChangedFor(nameof(GreetUserCommand))]" for every command you have on an "IsNotBusy" property, this would work too with the existing syntax
[RelayCommand(CanExecute = nameof(IsNotBusy))]
private void GreetUser(User? user)
{
    Console.WriteLine($"Hello {user!.Name}!");
}

// Maybe something like this which was in Prism where it can be applied after the command has been created
GreetUserCommand.ObservesCanExecute((() => IsNotBusy);
// An attribute
[ListenForPropertyChange(SourceProperty = nameof(IsBusy)]
 
//Which would generate source like:
 
override OnPropertyChanged(string propertyName)
{
    if (propertyName == nameof(IsBusy))
    {
        OnPropertyChanged(nameof(DependentProperty));
    }
}

OR// Something better entirely

Usage example

See API breakdown

Breaking change?

I'm not sure

Alternatives

  • This user behaviour is more rare than double tapping the same command/button, so it doesn't cause problems as often
  • Considered writing some reflection stuff and overriding IsBusy on every viewmodel but that would probably add too much boilerplate

Additional context

No response

Help us help you

No, just wanted to propose this

@BurkusCat BurkusCat added the feature request 📬 A request for new changes to improve functionality label Jan 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request 📬 A request for new changes to improve functionality
Projects
None yet
Development

No branches or pull requests

1 participant