使用MVVM的MahApps MessageBoxes

时间:2014-02-27 23:46:32

标签: c# wpf mvvm caliburn.micro mahapps.metro

MahApps Merry Men的简单问题。我已经使用Caliburn.Micro使用你的伟大的地铁风格的控件实现了MVVM的应用程序。新的消息对话框看起来很棒,但目前还没有明确的方法来启动这些对话框而不用编写我自己的包装器(我不反对)。但是,这已经完成了,或者是否有我遗漏的东西,以便我可以从视图模型中调用消息框而不用大惊小怪?

感谢您的时间。

4 个答案:

答案 0 :(得分:19)

我创建了一个包装器来调用MahApps.Metro消息对话框,因为我的MVVM项目遇到了同样的问题。我必须创建一个打开的窗口列表,第一个窗口将始终是我的MainWindow。

这是我的DialogService代码:

public async Task<MessageDialogResult> ShowMessage(string message, MessageDialogStyle dialogStyle)
{
    var metroWindow = (_openedViews.First() as MetroWindow);
    metroWindow.MetroDialogOptions.ColorScheme = MetroDialogColorScheme.Accented;

    return await metroWindow.ShowMessageAsync("MY TITLE", message, dialogStyle, metroWindow.MetroDialogOptions);
}

此代码可用于显示带或不带结果的对话框。您可以注意到它的返回值为Task<MessageDialogResult>,因此如果您想获得结果,可以在ViewModel上执行此操作:

MessageDialogResult result = await _dialog.ShowMessage("SOME MESSAGE HERE", MessageDialogStyle.AffirmativeAndNegative).ConfigureAwait(false);

if (result == MessageDialogResult.Affirmative)
{
    //Do something
}

顺便说一下,如果调用ShowMessage()的方法需要一个结果,那么必须async放在分配上,否则它将无效。 (如果您只想显示消息对话框,则没有必要)。

我的项目正在使用Framework 4.0,由于我必须从NuGet安装的软件包,我只能使用async/await。 您可以访问此link以获取此软件包的MSDN文档,然后您可以下载软件包here

我希望它已经解决了你的问题。

修改

我在DialogService上实现了一个方法,可以从任何ViewModel打开任何窗口。此方法使用Microsoft Unity框架来实例化我的对象,然后我调用Show()来打开自己。在致电Show()之前,我将此窗口添加到列表中。

请参阅我的代码:

public void ShowView<T>(params ParameterOverride[] parameter)
{
    var window = UnityServiceConfigurator.Instance.Container.Resolve<T>(parameter) as MetroWindow;

    if (window != null)
    {
        if (Application.Current.MainWindow != window)
        {
            window.Owner = Application.Current.MainWindow;
            var ownerMetroWindow = (window.Owner as MetroWindow);

            if (!ownerMetroWindow.IsOverlayVisible())
                ownerMetroWindow.ShowOverlayAsync();
        }

        if (!_openedViews.Contains(window))
            _openedViews.Add(window);

        window.Show();
    }
}

这是我从ViewModel调用的方式:

_dialog.ShowView<MyView>();

如果整个软件上只有一个窗口,则可以保存其引用并使用它来显示ShowMessageAsync(),而无需仅创建列表以使用First。像这样:

var metroWindow = (Application.Current.MainWindow as MetroWindow);

答案 1 :(得分:19)

从1.1.3-ALPHA *(变为1.2.0)开始,MahApps提供了一个帮助程序,可以从VM启动对话框,它可以在多个窗口设置中运行:

1)使用Window中的附加属性,使用对话框子系统注册视图模型。

假设您的View的DataContext设置为您想要启动对话框的视图模型,请添加以下属性:

<Controls:MetroWindow 
    xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
    Dialog:DialogParticipation.Register="{Binding}">

2)抓取/注入DialogCoordinator:

new MainWindowViewModel(DialogCoordinator.Instance);

3)从视图模型中显示对话框。使用&#34;这个&#34;作为上下文,所以MahApps可以将您的视图模型与正确的窗口结合:

_dialogCoordinator.ShowMessageAsync(this, "Message from VM", "MVVM based dialogs!")

答案 2 :(得分:0)

如果您只显示一个窗口实例,可以尝试这样的事情:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Caliburn.Micro;
using MahApps.Metro.Controls;
using MahApps.Metro.Controls.Dialogs;

namespace Busyboy
{
    [Export(typeof(IShell))]
    class MainViewModel : PropertyChangedBase, IShell
    {
        public void StartPomodoro()
        {
            var mainview0 = System.Windows.Application.Current.Windows.OfType<MainView>().FirstOrDefault();
            mainview0.ShowInputAsync("New Pomodoro", "Enter a name for new pomodoro session.");
        }
    }
}

而且,您应该有一种识别每个窗口的方法,以便您可以过滤掉窗口。 请注意导入&#34; Metro.Controls.Dialogs&#34;其中包含扩展名。

答案 3 :(得分:0)

我能够通过首先将Dialog父级设置为Conductor<Screen>来使其工作。然后,在执行启动对话框的某些VM操作中,我只需执行以下操作:

public async Task LaunchDialog(MyDialogVM vm)
{
   var customDialog = new CustomDialog { Title = "Some Title" };
   var view = new MyDialogView{DataContext = vm};   // instance of the view user control
   customDialog.Content = view;
   // this registers the vm with CaliburnMicro, hence all life-cycle events are available
   ActivateItem(vm);    

   await _dialogCoordinator.ShowMetroDialogAsync(this, customDialog);

}