CommandZero

FunctionZero.CommandZero

Fully featured ICommand implementation NuGet package here

Usage

CommandZeroAsync uses fluent API to build ICommand instances quickly and easily, like this:

ICommand CabbagesCommand = new CommandBuilder()
                .SetExecuteAsync(DoSomethingAsync)
                .SetCanExecute(CanDoSomething)
                .AddGuard(this)
                .SetName("Cabbages")
                .SetExceptionHandler(CabbagesExceptionHandler)
                // More builder methods can go here ...
                .Build(); 

Where

private async Task DoSomethingAsync()
{
    // Do something awesome
}
private bool CanDoSomething()
{
    return CanDoSomethingAwesome;
}
private void CabbagesExceptionHandler(ICommandZero sourceCommand, Exception ex)
{
    Logger.Log("Not quite awesome yet");
}

Many Builder methods have sensible overloads, for example SetExecuteAsync, SetExecute and SetCanExecute can take a CommandParameter:

Or with lambda functions:

For the async-averse there are synchronous SetExecute builder methods.

IGuard

Are your ViewModels littered with IsBusy flags? Now you can remove them all. Every Command that shares the same IGuard implementation will be disabled if any one of them is performing a long-running task. In the following example, assuming a Button is bound to GetDataCommand and another Button is bound to NextCommand, clicking the 'Get Data' button will disable both Commands, and therefore both Buttons, for 5 seconds

If your ViewModel implements IGuard, that simply becomes .AddGuard(this) The MvvmZero NuGet package has MvvmZeroBaseVm that implements IGuard

Command Text (formerly 'FriendlyName')

.SetName(string name) sets a Text property on the Command that the UI can bind to. Alternatively, .SetName(Func<string>) sets a method that is called to evaluate the Text property.

Automatically calling ChangeCanExecute

If there is need to re-evaluate the result of CanExecute, it is up to the developer to call ChangeCanExecute so UI (usually a Button) can update its IsEnabled flag. This is often done in an OnPropertyChanged overload on the ViewModel Alternatively, you can call .AddObservedProperty to specify the property or properties that will trigger such a re-evaluation Caution May leak if you recycle your ViewModel and your Commands are built outside of your constructor, or if you specify a property on an object outside the scope of your ViewModel

Builder methods:

Adds a global guard implementation. Commands that share a guard cannot execute concurrently. Commands can be given multiple guard implementations, though individual guard implementations can only be added once CAUTION Watch out for deadlock if you use the same Guard across multiple Pages. Recommendation: Implement IGuard in your ViewModel base class, e.g. by delegating to an instance of BasicGuard, so you can use the ViewModel ('this') as your Guard.

Adds a guard implementation. Commands that share a guard cannot execute concurrently. Commands can be given multiple guard implementations, though individual guard implementations can only be added once CAUTION Watch out for deadlock if you use the same Guard across multiple Pages. Recommendation: Implement IGuard in your ViewModel base class, e.g. by delegating to an instance of BasicGuard, so you can use the 'this' as your Guard.

The command can automatically re-evaluate the CanExecute delegate when a specified property changes, allowing any UI controls that are bound to the Command to update their IsEnabled status. propertySource : An object that supports INotifyPropertyChanged propertyName : The name of a property on propertySource Caution May leak if you recycle your ViewModel and your Commands are built outside of your constructor, or if you specify a property on an object outside the scope of your ViewModel

The command can automatically re-evaluate the CanExecute delegate when a specified property changes, allowing any UI controls that are bound to the Command to update their IsEnabled status. propertySource : An object that supports INotifyPropertyChanged propertyNames : Comma separated list of propertyNames found on propertySource Caution May leak if you recycle your ViewModel and your Commands are built outside of your constructor, or if you specify a property on an object outside the scope of your ViewModel

Build the Command :)

Set a CanExecute callback that does not require a parameter

Set a CanExecute callback that requires a parameter

Set a synchonous Execute callback that does not require a parameter. Prefer the async overload!

Set a synchonous Execute callback that requires a parameter. Prefer the async overload!

Set an asynchronous Execute callback that requires a parameter

Set an asynchronous Execute callback that does not require a parameter

Sets a delegate that can be used to retrieve the name of the Command. The UI can then bind to the Text property Useful for internationalisation

Sets the name of the Command. The UI can then bind to the Text property Useful for internationalisation.

Sets a callback for if you want to capture any exceptions thrown by a Command.

Last updated