Alright. Using Task based Asynchronous Pattern your requirement is trivial thing to do.
You need some sort of AsynchronousCommand
which we don't have yet in framework. We can create it ourself with little effort.
public interface IAsyncCommand : ICommand
{
Task ExecuteAsync(object parameter);
}
You need composite implementation of this interface which goes as follows
public class AsyncCompositeCommand : IAsyncCommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private readonly IEnumerable<IAsyncCommand> commands;
private readonly Action<object> executedCallback;
public AsyncCompositeCommand(IEnumerable<IAsyncCommand> commands, Action<object> executedCallback)
{
this.commands = commands;
this.executedCallback = executedCallback;
}
public bool CanExecute(object parameter)
{
return commands.Any(x => x.CanExecute(parameter));
}
public async Task ExecuteAsync(object parameter)
{
var pendingTasks = commands.Select(c=> c.ExecuteAsync(parameter))
.ToList();
await Task.WhenAll(pendingTasks);
executedCallback(parameter);//Notify
}
public async void Execute(object parameter)
{
await ExecuteAsync(parameter);
}
}
In above class ExecuteAsync
starts other child commands in parallel. If you prefer it to be sequential, you can replace the ExecuteAsync
method with below implementation.
public async Task ExecuteAsync(object parameter)
{
foreach (var cmd in commands)
{
await cmd.ExecuteAsync(parameter);
}
executedCallback(parameter);//Notify
}
executedCallback
is a delegate which will be called when all of the child commands are done. You can have your window close code wrapped in that delegate.
Your view model would look something like this:
public class ViewModel
{
public ICommand SaveCommand { get; private set; }
public ViewModel()
{
SaveCommand = new AsyncCompositeCommand(new IAsyncCommand[]
{
command1,
command2,
...
},
param => Console.WriteLine("Done"));
}
}
It's up to you how you bind ViewModel.SaveCommand
property in UI.