Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 等待MahApps Metro对话框返回结果_C#_Wpf_Mvvm_Mvvm Light_Mahapps.metro - Fatal编程技术网

C# 等待MahApps Metro对话框返回结果

C# 等待MahApps Metro对话框返回结果,c#,wpf,mvvm,mvvm-light,mahapps.metro,C#,Wpf,Mvvm,Mvvm Light,Mahapps.metro,我有一个ViewModel向视图发送消息(使用MVVM Light Messenger),以显示Metro对话框,如下所示: 在ViewModel中,我从DialogBox类调用以下代码: DialogBox.ShowDialogBox( (result) => { DialogResult(result); }, "Dialog Title",

我有一个ViewModel向视图发送消息(使用MVVM Light Messenger),以显示Metro对话框,如下所示:

在ViewModel中,我从DialogBox类调用以下代码:

DialogBox.ShowDialogBox(
                        (result) => { DialogResult(result); },
                        "Dialog Title",
                        "Dialog Message",
                        MessageDialogStyle.AffirmativeAndNegative
                        );
这是DialogBox类,用于将消息发送到视图:

public class DialogBox
{
    public Action<MessageDialogResult> dialogResultCallBack { get; set; }
    public string dialogTitle;
    public string dialogText;
    public MessageDialogStyle dialogStyle;
    public string okButtonText;
    public string cancelButtonText;

    public DialogBox(Action<MessageDialogResult> _dialogResultCallBack, string _dialogTitle, string _dialogText, MessageDialogStyle _dialogStyle, string _okButtonText, string _cancelButtonText)
    {
        dialogResultCallBack = _dialogResultCallBack;
        dialogTitle = _dialogTitle;
        dialogText = _dialogText;
        dialogStyle = _dialogStyle;
        okButtonText = _okButtonText;
        cancelButtonText = _cancelButtonText;
    }


    public static void ShowDialogBox(Action<MessageDialogResult> _dialogResultCallBack, string _dialogTitle, string _dialogText,
        MessageDialogStyle _dialogStyle, string _affirmativeButtonText = "OK", string _negativeButtonText = "Cancel")
    {
        Messenger.Default.Send(new DialogBox(
                       _dialogResultCallBack,
                       _dialogTitle,
                       _dialogText,
                       _dialogStyle,
                       _affirmativeButtonText,
                       _negativeButtonText), GlobalResources.MessengerTokens.dialogTokenMainWindow);
    }
}
实际上,我希望在调用ViewModel中的DialogBox.ShowDialogBox()方法后立即等待结果。当前的方法导致代码跳转到单独的方法调用,而不是直接处理结果。为了简单地说明这一点

if(condition)
{
  DialogBox.ShowDialogBox(...);

  //Needs some sort of await method to wait for results here

  if(result == MessageDialogResult.Affirmative)
  {
         //do stuff
  }
  else
  {
        //do stuff
  }
 }
我至少在WinForms上看到过一些示例代码,通过执行以下操作,等待结果更容易(使用codebehind和不使用MVVM):

if (MessageBox.Show("Title", "Message", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.OK)

对于我目前的处境,我可以采取类似的方法吗?谢谢你的建议,如果我的问题太长,我很抱歉

我认为有更好的方法来做你正在做的事情。为了让这个更MVVM,这就是我所做的。。。首先,我使用Caliburn Micro来处理我的MVVM和MEF。首先我们有两个接口:

internal interface IDialogViewModel
{
    event EventHandler Closed;
}
下面的界面将帮助您获得对话框的结果

public interface IDialogManager
{
    /// <summary>
    /// Show a dialog that performs as Task with generic return type. 
    /// </summary>
    /// <typeparam name="TResult">The result to be returned from the dialog task.</typeparam>
    /// <param name="viewModel">The DialogViewModel type to be displayed.</param>
    /// <returns>The Task to be awaited.</returns>
    Task<TResult> ShowDialog<TResult>(DialogViewModel<TResult> viewModel);

    /// <summary>
    /// Show a dialog that performs as Task.
    /// </summary>
    /// <param name="viewModel">The result to be returned from the dialog task.</param>
    /// <returns>The Task to be awaited.</returns>
    Task ShowDialog(DialogViewModel viewModel);
}
公共接口IDialogManager
{
/// 
///显示一个对话框,该对话框以泛型返回类型作为任务执行。
/// 
///要从对话框任务返回的结果。
///要显示的对话框ViewModel类型。
///等待的任务。
任务显示对话框(对话框视图模型视图模型);
/// 
///显示作为任务执行的对话框。
/// 
///要从对话框任务返回的结果。
///等待的任务。
任务显示对话框(对话框视图模型视图模型);
}
这些接口的实现是

/// <summary>
/// DialogViewModel class which should be inherited for all view 
/// model that want to be displayed as metro dialogs.
/// </summary>
public abstract class DialogViewModel : Screen, IDialogViewModel
{
    private readonly TaskCompletionSource<int> tcs;
    internal Task Task { get { return tcs.Task; } }

    /// <summary>
    /// Deafult constructor.
    /// </summary>
    protected DialogViewModel()
    {
        tcs = new TaskCompletionSource<int>();
    }

    /// <summary>
    /// Close the dialog.
    /// </summary>
    protected void Close()
    {
        tcs.SetResult(0);
        var handler = Closed;
        if (handler != null)
            handler(this, EventArgs.Empty);
    }

    /// <summary>
    /// Closed event.
    /// </summary>
    public event EventHandler Closed;
}

/// <summary>
/// DialogViewModel class which should be inherited for all view 
/// model that want to be displayed as metro dialogs that can return a 
/// specific result.
/// </summary>
public abstract class DialogViewModel<TResult> : Screen, IDialogViewModel
{
    private readonly TaskCompletionSource<TResult> tcs;
    internal Task<TResult> Task { get { return tcs.Task; } }

    /// <summary>
    /// Deafult constructor.
    /// </summary>
    protected DialogViewModel()
    {
        tcs = new TaskCompletionSource<TResult>();
    }

    /// <summary>
    /// Close the dialog.
    /// </summary>
    protected void Close(TResult result)
    {
        tcs.SetResult(result);
        var handler = Closed;
        if (handler != null)
            handler(this, EventArgs.Empty);
    }

    /// <summary>
    /// Closed event.
    /// </summary>
    public event EventHandler Closed;
}
//
///应为所有视图继承的DialogViewModel类
///要显示为高速对话框的模型。
/// 
公共抽象类DialogViewModel:Screen,IDialogViewModel
{
专用只读任务完成源tcs;
内部任务任务{get{return tcs.Task;}
/// 
///迪福尔特构造器。
/// 
受保护的DialogViewModel()
{
tcs=新任务完成源();
}
/// 
///关闭对话框。
/// 
受保护的无效关闭()
{
tcs.SetResult(0);
var handler=Closed;
if(处理程序!=null)
处理程序(此,EventArgs.Empty);
}
/// 
///闭幕式。
/// 
公共事件处理程序关闭;
}
/// 
///应为所有视图继承的DialogViewModel类
///希望显示为可以返回
///具体结果。
/// 
公共抽象类DialogViewModel:Screen,IDialogViewModel
{
专用只读任务完成源tcs;
内部任务任务{get{return tcs.Task;}
/// 
///迪福尔特构造器。
/// 
受保护的DialogViewModel()
{
tcs=新任务完成源();
}
/// 
///关闭对话框。
/// 
受保护的无效关闭(TResult结果)
{
tcs.SetResult(结果);
var handler=Closed;
if(处理程序!=null)
处理程序(此,EventArgs.Empty);
}
/// 
///闭幕式。
/// 
公共事件处理程序关闭;
}
经理班是

/// <summary>
/// The DialogManager that can be used to show Views as Metro modal dialogs.
/// Import IDialogManager to any view model that needs to show a metro message 
/// box.
/// </summary>
[Export(typeof(IDialogManager))]
public class DialogManager : IDialogManager
{
    /// <summary>
    /// Show the required dialog.
    /// </summary>
    /// <param name="viewModel">The view model ascociated with the view.</param>
    public async Task ShowDialog(DialogViewModel viewModel)
    {
        // Locate the ascociated view.
        var viewType = ViewLocator.LocateTypeForModelType(viewModel.GetType(), null, null);
        var dialog = (BaseMetroDialog)Activator.CreateInstance(viewType);
        if (dialog == null)
        {
            throw new InvalidOperationException(
                String.Format("The view {0} belonging to view model {1} " +
                                  "does not inherit from {2}",
                                  viewType,
                                  viewModel.GetType(),
                                  typeof(BaseMetroDialog)));
        }
        dialog.DataContext = viewModel;

        // Show the metro window.
        MetroWindow firstMetroWindow = 
            Application.Current.Windows.OfType<MetroWindow>().First();
        await firstMetroWindow.ShowMetroDialogAsync(dialog);
        await viewModel.Task;
        await firstMetroWindow.HideMetroDialogAsync(dialog);
    }

    /// <summary>
    /// Show the required dialog.
    /// </summary>
    /// <typeparam name="TResult">The type of result to return.</typeparam>
    /// <param name="viewModel">The view model ascociated with the view.</param>
    public async Task<TResult> ShowDialog<TResult>(DialogViewModel<TResult> viewModel)
    {
        // Locate the ascociated view.
        var viewType = ViewLocator.LocateTypeForModelType(viewModel.GetType(), null, null);
        var dialog = (BaseMetroDialog)Activator.CreateInstance(viewType);
        if (dialog == null)
        {
            throw new InvalidOperationException(
                String.Format("The view {0} belonging to view model {1} " +
                                  "does not inherit from {2}",
                                  viewType,
                                  viewModel.GetType(),
                                  typeof(BaseMetroDialog)));
        }
        dialog.DataContext = viewModel;

        // Show the metro window.
        MetroWindow firstMetroWindow = Application.Current.Windows.OfType<MetroWindow>().First();
        await firstMetroWindow.ShowMetroDialogAsync(dialog);
        TResult result = await viewModel.Task;
        await firstMetroWindow.HideMetroDialogAsync(dialog);
        return result;
    }
}
//
///可用于将视图显示为高速模式对话框的DialogManager。
///将IDialogManager导入任何需要显示高速消息的视图模型
///盒子。
/// 
[导出(类型(IDialogManager))]
公共类DialogManager:IDialogManager
{
/// 
///显示所需的对话框。
/// 
///视图模型与视图关联。
公共异步任务ShowDialog(DialogViewModel viewModel)
{
//找到关联视图。
var viewType=ViewLocator.LocateTypeForModelType(viewModel.GetType(),null,null);
var dialog=(BaseMetroDialog)Activator.CreateInstance(viewType);
如果(对话框==null)
{
抛出新的InvalidOperationException(
Format(“属于视图模型{1}的视图{0}”+
“不从{2}继承”,
视图类型,
viewModel.GetType(),
类型(BaseMetroDialog));
}
dialog.DataContext=viewModel;
//显示地铁窗口。
MetroWindow firstMetroWindow=
Application.Current.Windows.OfType().First();
等待firstMetroWindow.ShowMetroDialogAsync(对话框);
等待viewModel.Task;
等待firstMetroWindow.HideMetroDialogAsync(对话框);
}
/// 
///显示所需的对话框。
/// 
///要返回的结果的类型。
///视图模型与视图关联。
公共异步任务ShowDialog(DialogViewModel viewModel)
{
//找到关联视图。
var viewType=ViewLocator.LocateTypeForModelType(viewModel.GetType(),null,null);
var dialog=(BaseMetroDialog)Activator.CreateInstance(viewType);
如果(对话框==null)
{
抛出新的InvalidOperationException(
Format(“属于视图模型{1}的视图{0}”+
“不从{2}继承”,
视图类型,
viewModel.GetType(),
类型(BaseMetroDialog));
}
dialog.DataContext=viewModel;
//显示地铁窗口。
MetroWindow firstMetroWindow=Application.Current.Windows.OfType().First();
等待firstMetroWindow.ShowMetroDialogAsync(对话框);
TResult result=wait viewModel.Task;
等待firstMetroWindow.HideMetroDialogAsync(对话框);
返回结果;
}
}
我们还有消息框设置

/// <summary>
/// Class that holds the settings for message box dialogs.
/// </summary>
public class MessageBoxSettings
{
    /// <summary>
    /// Default constructor.
    /// </summary>
    public MessageBoxSettings()
    {
        this.AffirmativeButtonText = "OK";
        this.NegativeButtonText = "Cancel";
        this.MessageDialogStyle = MessageDialogStyle.AffirmativeAndNegative;
        this.MetroColorDialogScheme = MetroDialogColorScheme.Theme;
        this.Animation = false;
    }

    /// <summary>
    /// Sets the button styles to use.
    /// Default is 'OK' and 'Cancel'.
    /// </summary>
    public MessageDialogStyle MessageDialogStyle { get; set; }

    /// <summary>
    /// The color sheme to use for the dialog.
    /// </summary>
    public MetroDialogColorScheme MetroColorDialogScheme { get; set; }

    /// <summary>
    /// Affirmative button text. Default OK.
    /// </summary>
    public string AffirmativeButtonText { get; set; }

    /// <summary>
    /// The negative button text to use.
    /// </summary>
    public string NegativeButtonText { get; set; }

    /// <summary>
    /// First auxillary button text.
    /// </summary>
    public string FirstAuxillaryButtonText { get; set; }

    /// <summary>
    /// Second auxillary button text.
    /// </summary>
    public string SecondAuxiliaryButtonText { get; set; }

    /// <summary>
    /// Show animation on the dialog.
    /// </summary>
    public bool Animation { get; set; }
}
//
///类,该类保存消息框对话框的设置。
/// 
公共类消息框
/// <summary>
/// The DialogManager that can be used to show Views as Metro modal dialogs.
/// Import IDialogManager to any view model that needs to show a metro message 
/// box.
/// </summary>
[Export(typeof(IDialogManager))]
public class DialogManager : IDialogManager
{
    /// <summary>
    /// Show the required dialog.
    /// </summary>
    /// <param name="viewModel">The view model ascociated with the view.</param>
    public async Task ShowDialog(DialogViewModel viewModel)
    {
        // Locate the ascociated view.
        var viewType = ViewLocator.LocateTypeForModelType(viewModel.GetType(), null, null);
        var dialog = (BaseMetroDialog)Activator.CreateInstance(viewType);
        if (dialog == null)
        {
            throw new InvalidOperationException(
                String.Format("The view {0} belonging to view model {1} " +
                                  "does not inherit from {2}",
                                  viewType,
                                  viewModel.GetType(),
                                  typeof(BaseMetroDialog)));
        }
        dialog.DataContext = viewModel;

        // Show the metro window.
        MetroWindow firstMetroWindow = 
            Application.Current.Windows.OfType<MetroWindow>().First();
        await firstMetroWindow.ShowMetroDialogAsync(dialog);
        await viewModel.Task;
        await firstMetroWindow.HideMetroDialogAsync(dialog);
    }

    /// <summary>
    /// Show the required dialog.
    /// </summary>
    /// <typeparam name="TResult">The type of result to return.</typeparam>
    /// <param name="viewModel">The view model ascociated with the view.</param>
    public async Task<TResult> ShowDialog<TResult>(DialogViewModel<TResult> viewModel)
    {
        // Locate the ascociated view.
        var viewType = ViewLocator.LocateTypeForModelType(viewModel.GetType(), null, null);
        var dialog = (BaseMetroDialog)Activator.CreateInstance(viewType);
        if (dialog == null)
        {
            throw new InvalidOperationException(
                String.Format("The view {0} belonging to view model {1} " +
                                  "does not inherit from {2}",
                                  viewType,
                                  viewModel.GetType(),
                                  typeof(BaseMetroDialog)));
        }
        dialog.DataContext = viewModel;

        // Show the metro window.
        MetroWindow firstMetroWindow = Application.Current.Windows.OfType<MetroWindow>().First();
        await firstMetroWindow.ShowMetroDialogAsync(dialog);
        TResult result = await viewModel.Task;
        await firstMetroWindow.HideMetroDialogAsync(dialog);
        return result;
    }
}
/// <summary>
/// Class that holds the settings for message box dialogs.
/// </summary>
public class MessageBoxSettings
{
    /// <summary>
    /// Default constructor.
    /// </summary>
    public MessageBoxSettings()
    {
        this.AffirmativeButtonText = "OK";
        this.NegativeButtonText = "Cancel";
        this.MessageDialogStyle = MessageDialogStyle.AffirmativeAndNegative;
        this.MetroColorDialogScheme = MetroDialogColorScheme.Theme;
        this.Animation = false;
    }

    /// <summary>
    /// Sets the button styles to use.
    /// Default is 'OK' and 'Cancel'.
    /// </summary>
    public MessageDialogStyle MessageDialogStyle { get; set; }

    /// <summary>
    /// The color sheme to use for the dialog.
    /// </summary>
    public MetroDialogColorScheme MetroColorDialogScheme { get; set; }

    /// <summary>
    /// Affirmative button text. Default OK.
    /// </summary>
    public string AffirmativeButtonText { get; set; }

    /// <summary>
    /// The negative button text to use.
    /// </summary>
    public string NegativeButtonText { get; set; }

    /// <summary>
    /// First auxillary button text.
    /// </summary>
    public string FirstAuxillaryButtonText { get; set; }

    /// <summary>
    /// Second auxillary button text.
    /// </summary>
    public string SecondAuxiliaryButtonText { get; set; }

    /// <summary>
    /// Show animation on the dialog.
    /// </summary>
    public bool Animation { get; set; }
}
/// <summary>
/// View model for the message box view.
/// </summary>
public class MessageBoxViewModel : DialogViewModel<MessageDialogResult>
{
    private MessageBoxSettings settings;

    #region Initialisation.
    /// <summary>
    /// Null.
    /// </summary>
    public MessageBoxViewModel() { }

    /// <summary>
    /// Default constructor.
    /// </summary>
    /// <param name="title">The title of the message box dialog.</param>
    /// <param name="message">The message to display in the message box.</param>
    public MessageBoxViewModel(string title, string message)
    {
        this.Title = title;
        this.DialogBody = message;
        if (this.settings == null)
            this.settings = new MessageBoxSettings();
        SetDialogVisuals();
    }

    /// <summary>
    /// Overloaded.
    /// </summary>
    /// <param name="title">The title of the message box dialog.</param>
    /// <param name="message">The message to display in the message box.</param>
    /// <param name="settings">MessageBoxSettings for the dialog.</param>
    public MessageBoxViewModel(string title, string message, MessageBoxSettings settings)
    {
        this.Title = title;
        this.DialogBody = message;
        this.settings = settings;
        SetDialogVisuals();
    }
    #endregion // Initialisation.

    #region Class Methods.
    /// <summary>
    /// Set the dialog visuals based on the MessageBoxSettings.
    /// </summary>
    private void SetDialogVisuals()
    {
        // Set dialog button visibility.
        switch (settings.MessageDialogStyle)
        {
            case MessageDialogStyle.Affirmative:
                this.AffirmativeButtonVisibility = Visibility.Visible;
                this.NegativeButtonVisibility = Visibility.Collapsed;
                this.FirstAuxillaryButtonVisibility = Visibility.Collapsed;
                this.SecondAuxillaryButtonVisibility = Visibility.Collapsed;
                break;
            case MessageDialogStyle.AffirmativeAndNegative:
                this.AffirmativeButtonVisibility = Visibility.Visible;
                this.NegativeButtonVisibility = Visibility.Visible;
                this.FirstAuxillaryButtonVisibility = Visibility.Collapsed;
                this.SecondAuxillaryButtonVisibility = Visibility.Collapsed;
                break;
            case MessageDialogStyle.AffirmativeAndNegativeAndDoubleAuxiliary:
                this.AffirmativeButtonVisibility = Visibility.Visible;
                this.NegativeButtonVisibility = Visibility.Visible;
                this.FirstAuxillaryButtonVisibility = Visibility.Visible;
                this.SecondAuxillaryButtonVisibility = Visibility.Visible;
                break;
            case MessageDialogStyle.AffirmativeAndNegativeAndSingleAuxiliary:
                this.AffirmativeButtonVisibility = Visibility.Visible;
                this.NegativeButtonVisibility = Visibility.Visible;
                this.FirstAuxillaryButtonVisibility = Visibility.Visible;
                this.SecondAuxillaryButtonVisibility = Visibility.Collapsed;
                break;
            default:
                break;
        }

        // Set the button text.
        this.AffirmativeButtonText = settings.AffirmativeButtonText;
        this.NegativeButtonText = settings.NegativeButtonText;
        this.FirstAuxillaryButtonText = settings.FirstAuxillaryButtonText;
        this.SecondAuxiliaryButtonText = settings.SecondAuxiliaryButtonText;

        // Color scheme.
        string name = MahApps.Metro.ThemeManager.DetectAppStyle(Application.Current).Item2.Name;
        this.Background = settings.MetroColorDialogScheme == MetroDialogColorScheme.Theme ?
            MahApps.Metro.ThemeManager.Accents
                .Where(a => a.Name.CompareNoCase(name))
                .First().Resources["HighlightBrush"] as SolidColorBrush :
            new SolidColorBrush(System.Windows.Media.Colors.White);
    }

    /// <summary>
    /// Handles the button click events for the affermative button.
    /// </summary>
    public void AffirmativeButtonClick()
    {
        Close(MessageDialogResult.Affirmative);
    }

    /// <summary>
    /// Handles the button click events for the negative button.
    /// </summary>
    public void NegativeButtonClick()
    {
        Close(MessageDialogResult.Negative);
    }

    /// <summary>
    /// Handles the button click events for the first auxillary button.
    /// </summary>
    public void FirstAuxillaryButtonClick()
    {
        Close(MessageDialogResult.FirstAuxiliary);
    }

    /// <summary>
    /// Handles the button click events for the second auxillary button.
    /// </summary>
    public void SecondAuxillaryButtonClick()
    {
        Close(MessageDialogResult.SecondAuxiliary);
    }
    #endregion // Class Methods.

    #region Properties.
    /// <summary>
    /// Hold the dialog title.
    /// </summary>
    private string title;
    public string Title
    {
        get { return title; }
        set
        {
            if (title == value)
                return;
            title = value;
            NotifyOfPropertyChange(() => Title);
        }
    }

    /// <summary>
    /// Hold the text for the dialog body.
    /// </summary>
    private string dialogBody;
    public string DialogBody
    {
        get { return dialogBody; }
        set
        {
            if (dialogBody == value)
                return;
            dialogBody = value;
            NotifyOfPropertyChange(() => DialogBody);
        }
    }

    /// <summary>
    /// Sets the button styles to use.
    /// Default is 'OK' and 'Cancel'.
    /// </summary>
    private MessageDialogStyle messageDialogStyle =
        MessageDialogStyle.AffirmativeAndNegative;
    public MessageDialogStyle MessageDialogStyle
    {
        get { return messageDialogStyle; }
        set
        {
            if (messageDialogStyle == value)
                return;
            messageDialogStyle = value;
            NotifyOfPropertyChange(() => MessageDialogStyle);
        }
    }

    /// <summary>
    /// The color sheme to use for the dialog.
    /// </summary>
    private SolidColorBrush background;
    public SolidColorBrush Background
    {
        get { return background; }
        set
        {
            if (background == value)
                return;
            background = value;
            NotifyOfPropertyChange(() => Background);
        }
    }

    /// <summary>
    /// Affirmative button text. Default OK.
    /// </summary>
    private string affirmativeButtonText = "OK";
    public string AffirmativeButtonText
    {
        get { return affirmativeButtonText; }
        set
        {
            if (affirmativeButtonText == value)
                return;
            affirmativeButtonText = value;
            NotifyOfPropertyChange(() => AffirmativeButtonText);
        }
    }

    /// <summary>
    /// Visibility for the default affirmative button.
    /// </summary>
    private Visibility affirmativeButtonVisibility = Visibility.Visible;
    public Visibility AffirmativeButtonVisibility
    {
        get { return affirmativeButtonVisibility = Visibility.Visible; }
        set
        {
            if (affirmativeButtonVisibility == value)
                return;
            affirmativeButtonVisibility = value;
            NotifyOfPropertyChange(() => AffirmativeButtonVisibility);
        }
    }

    /// <summary>
    /// The negative button text to use.
    /// </summary>
    private string negativeButtonText = "Cancel";
    public string NegativeButtonText
    {
        get { return negativeButtonText; }
        set
        {
            if (negativeButtonText == value)
                return;
            negativeButtonText = value;
            NotifyOfPropertyChange(() => NegativeButtonText);
        }
    }

    /// <summary>
    /// Visibility for the default negative button.
    /// </summary>
    private Visibility negativeButtonVisibility = Visibility.Visible;
    public Visibility NegativeButtonVisibility
    {
        get { return negativeButtonVisibility; }
        set
        {
            if (negativeButtonVisibility == value)
                return;
            negativeButtonVisibility = value;
            NotifyOfPropertyChange(() => NegativeButtonVisibility);
        }
    }

    /// <summary>
    /// First auxillary button text.
    /// </summary>
    private string firstAuxillaryButtonText;
    public string FirstAuxillaryButtonText
    {
        get { return firstAuxillaryButtonText; }
        set
        {
            if (firstAuxillaryButtonText == value)
                return;
            firstAuxillaryButtonText = value;
            NotifyOfPropertyChange(() => FirstAuxillaryButtonText);
        }
    }

    /// <summary>
    /// First auxillary button visibility.
    /// </summary>
    private Visibility firstAuxillaryButtonVisibility = Visibility.Collapsed;
    public Visibility FirstAuxillaryButtonVisibility
    {
        get { return firstAuxillaryButtonVisibility; }
        set
        {
            if (firstAuxillaryButtonVisibility == value)
                return;
            firstAuxillaryButtonVisibility = value;
            NotifyOfPropertyChange(() => FirstAuxillaryButtonVisibility);
        }
    }

    /// <summary>
    /// Second auxillary button text.
    /// </summary>
    private string secondAuxiliaryButtonText;
    public string SecondAuxiliaryButtonText
    {
        get { return secondAuxiliaryButtonText; }
        set
        {
            if (secondAuxiliaryButtonText == value)
                return;
            secondAuxiliaryButtonText = value;
            NotifyOfPropertyChange(() => SecondAuxiliaryButtonText);
        }
    }

    /// <summary>
    /// Second auxillary button visibility.
    /// </summary>
    private Visibility secondAuxillaryButtonVisibility = Visibility.Collapsed;
    public Visibility SecondAuxillaryButtonVisibility
    {
        get { return secondAuxillaryButtonVisibility; }
        set
        {
            if (secondAuxillaryButtonVisibility == value)
                return;
            secondAuxillaryButtonVisibility = value;
            NotifyOfPropertyChange(() => SecondAuxillaryButtonVisibility);
        }
    }
    #endregion // Properties.
}
<MahAppsDialogs:CustomDialog 
        x:Class="GambitFramework.Core.MessageBox.MessageBoxView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Caliburn="http://www.caliburnproject.org"
        xmlns:MahApps="http://metro.mahapps.com/winfx/xaml/controls"
        xmlns:Local="clr-namespace:GambitFramework.Core.MessageBox"
        xmlns:Converters="clr-namespace:GambitFramework.Core.Converters;assembly=GambitFramework"
        xmlns:MahAppsDialogs="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
        Title="{Binding Title}">
    <MahAppsDialogs:CustomDialog.Content>
        <TextBlock Text="{Binding DialogBody}"
                      Margin="0,5,0,0"
                      TextWrapping="Wrap"/>
    </MahAppsDialogs:CustomDialog.Content>
    <MahAppsDialogs:CustomDialog.DialogBottom>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="25*" />
                <ColumnDefinition Width="50*" />
                <ColumnDefinition Width="25*" />
            </Grid.ColumnDefinitions>
            <StackPanel Grid.Column="1"
                            Orientation="Horizontal" 
                            HorizontalAlignment="Right"
                            Margin="0,0,0,0">
                <Button x:Name="AffirmativeButton" 
                          Content="{Binding AffirmativeButtonText}"
                          Visibility="{Binding AffirmativeButtonVisibility}"
                          Style="{StaticResource AccentedSquareButtonStyle}"
                          Caliburn:Message.Attach="[Event Click] = [Action AffirmativeButtonClick()]"
                          MinWidth="75"
                          Padding="15,0"
                          Margin="5,10,0,5"/>
                <Button x:Name="NegativeButton" 
                          Content="{Binding NegativeButtonText}"
                          Visibility="{Binding NegativeButtonVisibility}" 
                          Caliburn:Message.Attach="[Event Click] = [Action NegativeButtonClick()]"
                          MinWidth="75"
                          Padding="15,0"
                          Margin="10,10,0,5"/>
                <Button x:Name="FirstAuxiliaryButton" 
                          Content="{Binding FirstAuxillaryButtonText}"
                          Visibility="{Binding FirstAuxillaryButtonVisibility}"
                          Caliburn:Message.Attach="[Event Click] = [Action FirstAuxillaryButtonClick()]"
                          MinWidth="75"
                          Padding="15,0"
                          Margin="5,10,0,5"/>
                <Button x:Name="SecondAuxiliaryButton" 
                          Content="{Binding SecondAuxiliaryButtonText}"
                          Visibility="{Binding SecondAuxillaryButtonVisibility}"
                          Caliburn:Message.Attach="[Event Click] = [Action SecondAuxillaryButtonClick()]"
                          MinWidth="75"
                          Padding="15,0"
                          Margin="5,10,0,5"/>
            </StackPanel>
        </Grid>
    </MahAppsDialogs:CustomDialog.DialogBottom>
</MahAppsDialogs:CustomDialog>
MessageBoxSettings settings = new MessageBoxSettings()
{
    MessageDialogStyle = MessageDialogStyle.AffirmativeAndNegative,
    MetroColorDialogScheme = MetroDialogColorScheme.Accented,
    AffirmativeButtonText = "Delete",
    NegativeButtonText = "Cancel"
};
string message = String.Format(
    "Are you sure you want to delete back test \"{0}\" {1}",
    SelectedBackTest.Name,
    SelectedBackTest.LastRun == null ? 
        String.Empty : 
        String.Format("which was late run on {0:G}?", SelectedBackTest.LastRun));
MessageDialogResult r = await dialogManager
    .ShowDialog<MessageDialogResult>(
        new MessageBoxViewModel("Confirm Delete", message, settings));
if (r == MessageDialogResult.Affirmative)
{
    ...
}
using SysThread = System.Threading;
using WpfThread = System.Windows.Threading;
using SysTasks = System.Threading.Tasks;
using MahCtl = MahApps.Metro.Controls;
using MahDlg = MahApps.Metro.Controls.Dialogs;
using Win32 = Microsoft.Win32;
using Wpf = System.Windows;
using SysCompMod = System.ComponentModel;
        [...]
        MahCtl.MetroWindow parentMetroWindow = Wpf.Application.Current.Windows.OfType<MahCtl.MetroWindow>().First();
        var metroDialogSettings = new MahDlg.MetroDialogSettings();
        metroDialogSettings.OwnerCanCloseWithDialog = true; //does not appear to have any effect
        metroDialogSettings.AnimateHide             = false;
        metroDialogSettings.AnimateShow             = false;
        [...]
        using( SysThread.CancellationTokenSource tokenSource = new SysThread.CancellationTokenSource() )
        {
            metroDialogSettings.CancellationToken = tokenSource.Token;
            SysTasks.Task<MahDlg.MessageDialogResult> task = MahDlg.DialogManager.ShowMessageAsync( parentMetroWindow, title, message, mahStyle, metroDialogSettings );
            // ReSharper disable once AccessToDisposedClosure
            SysCompMod.CancelEventHandler cancelEventHandler = (s, e) => tokenSource.Cancel();
            parentMetroWindow.Closing += cancelEventHandler;
            while( !(task.IsCompleted || task.IsCanceled || task.IsFaulted) )
                Wpf.Application.Current.Dispatcher.Invoke( WpfThread.DispatcherPriority.Background, new Action( delegate { } ) );
            parentMetroWindow.Closing -= cancelEventHandler;
            return responseFromMahAppsMessageDialogResult( type, task.Result );
        }