MahApps Merry Men 的简单问题。我已经使用 Caliburn.Micro 实现了一个应用程序,使用你伟大的 Metro 风格控件来处理 MVVM 的东西。新的消息对话框看起来很棒,但目前没有明确的方法来启动这些对话框而不编写我自己的包装器(我不反对)。但是,这是否已经完成,或者我是否遗漏了一些东西,以便我可以从视图模型中调用消息框而不用大惊小怪?
谢谢你的时间。
MahApps Merry Men 的简单问题。我已经使用 Caliburn.Micro 实现了一个应用程序,使用你伟大的 Metro 风格控件来处理 MVVM 的东西。新的消息对话框看起来很棒,但目前没有明确的方法来启动这些对话框而不编写我自己的包装器(我不反对)。但是,这是否已经完成,或者我是否遗漏了一些东西,以便我可以从视图模型中调用消息框而不用大惊小怪?
谢谢你的时间。
从 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!")
我创建了一个包装器来调用 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);
如果您只有一个窗口实例显示,您可以尝试以下操作:
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”。
通过首先使 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);
}