19

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

谢谢你的时间。

4

4 回答 4

20

从 1.1.3-ALPHA*(成为 1.2.0)开始,MahApps 提供了一个帮助程序来从 VM 启动对话框,该程序在多窗口设置中工作:

1)使用窗口中的附加属性将视图模型注册到对话框子系统。

假设您的 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)从视图模型中显示您的对话框。使用“this”作为上下文,以便 MahApps 可以将您的视图模型与正确的窗口结合:

_dialogCoordinator.ShowMessageAsync(this, "Message from VM", "MVVM based dialogs!")
于 2015-06-01T07:52:20.010 回答
19

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

这是我的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);
}

此代码可用于显示有或没有结果的对话框。你可以注意到它的返回是 a Task<MessageDialogResult>,所以如果你想得到结果,你可以像在你的 ViewModel 上那样做:

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

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

顺便说一句,如果调用的方法ShowMessage()需要一个结果,你必须进行async赋值,否则它将不起作用。(如果您只想显示消息对话框,则没有必要)。

async/await我的项目使用的是 Framework 4.0,由于我必须从 NuGet 安装包,我只能使用它。您可以访问此链接以获取此软件包的 MSDN 文档,也可以在此处下载该软件包。

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

编辑:

我已经实现了一种方法,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()而无需创建一个仅使用第一个的列表。像这样:

var metroWindow = (Application.Current.MainWindow as MetroWindow);
于 2014-03-03T11:34:31.080 回答
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.");
        }
    }
}

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

于 2015-02-07T16:05:55.643 回答
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);

}
于 2019-11-22T22:36:31.237 回答