The proper way to do this is to override CanClose in your ViewModel and perform the save, then let your VM close if the save was successful or prevent the closing if the save failed. This approach properly allows you to save asynchronously, wait for the completion and then let the dialog close if successful. Same way you have access to the buttons you have access to the DialogResult to find out what button the user clicked and go down a different path in your CanClose method. Here's a simple example which always lets the dialog close if the user clicked "Cancel", but if they click "Ok", the dialog only closes if IsComplete is true.
public override void CanClose(Action<bool> callback)
{
if (!this.DialogHost().DialogResult.Equals(DialogResult.Cancel))
{
callback(IsComplete);
}
else
base.CanClose(callback);
}
Here's an example of a CanClose method from TempHire, that performs a Save or RejectChanges. This is not from a dialog, but it's gonna be the same thing for you, except you won't ask the user first if they want to save.
public override void CanClose(Action<bool> callback)
{
if (UnitOfWork.HasChanges())
{
var dialogResult =
_dialogManager.ShowMessage("There are unsaved changes. Would you like to save your changes?",
DialogResult.Yes, DialogResult.Cancel, DialogButtons.YesNoCancel);
dialogResult.OnComplete(delegate
{
if (dialogResult.DialogResult == DialogResult.Yes)
{
Busy.AddWatch();
UnitOfWork.CommitAsync(saveResult => callback(true),
_errorHandler.HandleError)
.OnComplete(args => Busy.RemoveWatch());
}
if (dialogResult.DialogResult == DialogResult.No)
{
UnitOfWork.Rollback();
callback(true);
}
if (dialogResult.DialogResult == DialogResult.Cancel)
callback(false);
});
}
else
base.CanClose(callback);
}