我想使用WPF Prism + MahApps.Metro创建一个弹出窗口或对话框,其中包含选择确认(确定,取消)
我创建了自定义互动:
<i:Interaction.Triggers>
<interactionRequest:InteractionRequestTrigger SourceObject="{Binding DeleteConfirmationRequest, Mode=OneWay}">
<interactionRequest:PopupWindowAction>
<interactionRequest:PopupWindowAction.WindowContent>
<confirmation:ConfirmationDialog/>
</interactionRequest:PopupWindowAction.WindowContent>
</interactionRequest:PopupWindowAction>
</interactionRequest:InteractionRequestTrigger>
</i:Interaction.Triggers>
但是这将创建一个默认的WPF窗口,它不是城域风格的。如何将其更改为MahApps.Metro窗口?
也许,另一种方法是使用MahApps.Metro Dialogs,但我不知道如何在Prism中使用它。
有什么想法吗?
答案 0 :(得分:5)
您必须做两件事,创建新的 MetroWindow 对话框,然后覆盖 PopupWindowAction 以使用它们。这听起来很长,但只需要10分钟:
首先,创建自己的确认和通知窗口,继承自 MetroWindow ,就像任何其他 MetroWindow 一样。您可以从棱镜源复制原始的确认和通知窗口,并根据mahapps quick start的建议进行更改。 因此,确认窗口将类似于:
<Controls:MetroWindow x:Class="MyApp.DefaultPopupWindows.DefaultConfirmationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
MinWidth="300" MinHeight="150"
Title="{Binding Title}"
BorderBrush="{DynamicResource AccentColorBrush}"
BorderThickness="1">
<Grid x:Name="LayoutRoot" Margin="5">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ContentControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Content="{Binding Content}"/>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="OkButton" Content="OK" Width="75" Height="25" HorizontalAlignment="Right" Margin="0,10,0,0" Click="OkButton_Click" />
<Button x:Name="CancelButton" Content="Cancel" Width="75" Height="25" HorizontalAlignment="Right" Margin="20,10,0,0" Click="CancelButton_Click" />
</StackPanel>
</Grid>
</Controls:MetroWindow>
背后的相关代码:
using MahApps.Metro.Controls;
using Microsoft.Practices.Prism.Interactivity.InteractionRequest;
using System.Windows;
namespace MyApp.DefaultPopupWindows
{
/// <summary>
/// Interaction logic for ConfirmationChildWindow.xaml
/// </summary>
public partial class DefaultConfirmationWindow : MetroWindow
{
/// <summary>
/// Creates a new instance of ConfirmationChildWindow.
/// </summary>
public DefaultConfirmationWindow()
{
InitializeComponent();
}
/// <summary>
/// Sets or gets the <see cref="IConfirmation"/> shown by this window./>
/// </summary>
public IConfirmation Confirmation
{
get
{
return this.DataContext as IConfirmation;
}
set
{
this.DataContext = value;
}
}
private void OkButton_Click(object sender, RoutedEventArgs e)
{
this.Confirmation.Confirmed = true;
this.Close();
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.Confirmation.Confirmed = false;
this.Close();
}
}
}
接下来,您将创建自己的 PopupWindowAction ,扩展棱镜中的那个。在该类中,您将覆盖GetWindow函数:
protected override Window GetWindow(INotification notification)
{
MetroWindow wrapperWindow;
if (this.WindowContent != null)
{
wrapperWindow = new MetroWindow();
// If the WindowContent does not have its own DataContext, it will inherit this one.
wrapperWindow.DataContext = notification;
wrapperWindow.Title = notification.Title;
this.PrepareContentForWindow(notification, wrapperWindow);
}
else
{
wrapperWindow = this.CreateDefaultWindow(notification);
}
return wrapperWindow;
}
您还必须为&#34; CreateDefaultWindow&#34;提供您自己的实施。这将创建相应窗口的新 MetroWindow 版本:
protected new MetroWindow CreateDefaultWindow(INotification notification)
{
MetroWindow window = null;
if (notification is IConfirmation)
{
window = new DefaultPopupWindows.DefaultConfirmationWindow() { Confirmation = (IConfirmation)notification };
}
else
{
window = new DefaultPopupWindows.DefaultNotificationWindow() { Notification = notification };
}
return window;
}
最后,在您自己的视图/窗口中的 InteractionRequest 中,指定这个新的 PopupWindowAction ,而不是棱镜版本。
答案 1 :(得分:3)
我不知道你是否可以在prism 5.0中使用它,但是使用新的Prism 6.0(Github)你有一个虚拟方法CreateWindow,你可以子类化PopupWindowAction并覆盖它创建Metro窗口。我正在使用以下代码:
namespace KPP.Vision.Infrastructure.Interactions
{
public class MetroPopupWindowAction:PopupWindowAction
{
protected override Window CreateWindow()
{
return new MetroPopupWindowView();
}
}
}
答案 2 :(得分:2)
我遇到了同样的问题,我可以通过这些评论得到解决方案 我使用Prism 6
1)首先重写PopupWindowAction
/// <summary>
/// it creates a new metro window instead of a window
/// </summary>
/// <returns></returns>
protected override Window CreateWindow()
{
return new MetroPopupWindow();
}
/// <summary>
/// Creates a window with the notification type
/// </summary>
/// <param name="notification"></param>
/// <returns></returns>
private new Window CreateDefaultWindow(INotification notification)
{
Window window = null;
if (notification is IConfirmation)
{
window = new MetroConfirmationWindow {Confirmation = (IConfirmation) notification};
}
else
{
window = new MetroNotificationWindow {Notification = notification};
}
return window;
}
/// <summary>
/// Returns the window to display as part of the trigger action.
/// </summary>
/// <param name="notification">The notification to be set as a DataContext in the window.</param>
/// <returns></returns>
protected override Window GetWindow(INotification notification)
{
Window wrapperWindow;
if (WindowContent != null)
{
wrapperWindow = CreateWindow();
if (wrapperWindow == null)
throw new NullReferenceException("CreateWindow cannot return null");
// If the WindowContent does not have its own DataContext, it will inherit this one.
wrapperWindow.DataContext = notification;
wrapperWindow.Title = notification.Title;
PrepareContentForWindow(notification, wrapperWindow);
}
else
{
wrapperWindow = CreateDefaultWindow(notification);
}
// If the user provided a Style for a Window we set it as the window's style.
if (WindowStyle != null)
wrapperWindow.Style = WindowStyle;
return wrapperWindow;
}
2)创建MetroWindow,MetroNotificationWindow和MetroConfirmationWindow based in the default windows
实施例: 的 MetroPopupWindow.xaml 强>
<controls:MetroWindow x:Class="MetroPopupWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d"
Title="MetroPopupWindow" TitleCaps="False" SizeToContent="WidthAndHeight">
<Grid>
<ContentControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0"
Content="{Binding Content}" />
</Grid>
</controls:MetroWindow>
MetroNotificationWindow.xaml
<controls:MetroWindow x:Class="MetroNotificationWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
Title="Web Studio" TitleCaps="False" SizeToContent="WidthAndHeight">
<Grid x:Name="LayoutRoot" Margin="5">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ContentControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0"
Content="{Binding Content}" />
<Button x:Name="OKButton" Content="{lex:Loc Ok}" Width="75" Height="25" HorizontalAlignment="Right"
Margin="0,10,0,0" Grid.Row="1" Click="OKButton_Click" IsDefault="True" />
</Grid>
</controls:MetroWindow>
3)更改MetroPopupWindowAction的PopupWindowAction的所有引用 例如:
<i:Interaction.Triggers>
<!-- Trigger listening for the "Raised" event on the source object (of type IInteractionRequest) -->
<interactionRequest:InteractionRequestTrigger
SourceObject="{Binding SaveChangesConfirmationRequest, Mode=OneWay}">
<!-- That window will be show as a modal dialog and centered over this window -->
<windowAction:MetroPopupWindowAction IsModal="True" CenterOverAssociatedObject="True" />
</interactionRequest:InteractionRequestTrigger>
</i:Interaction.Triggers>
答案 3 :(得分:2)
现在您不需要做任何自定义内容,也不需要使用InteractionRequests。
您可以查看MahApps.Metro.Demo.Samples(在github上)并检查MVVM的所有预配置对话框(在这种情况下,“对话框&gt;通过VM显示InputDialog”)。
这很简单,你需要: 1)注册DialogCoordinator @你的引导程序(使用Autofac的例子:)
builder.RegisterType<DialogCoordinator>().As<IDialogCoordinator>().SingleInstance();
2)使用Window中的附加属性,使用对话框子系统注册视图模型。 (这需要放在要从中调用对话框的ViewModel的View.xaml中:
<UserControl x:Class="MyNamespace.Views.MyView"
xmlns:dialogs="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
dialogs:DialogParticipation.Register="{Binding}"
.../>
3)@您的ViewModel,确保您对DialogCoordinator接口有一个只读引用,用于依赖注入:
namespace MyNamespace
{
class MyViewModel : BindableBase
{
readonly IDialogCoordinator _dialogCoordinator;
public MyViewModel (IDialogCoordinator dcFromDependencyInjection)
{
_dialogCoordinator = dcFromDependencyInjection;
[rest of your constructor code here]
}
}
}
4)现在,只要您需要从ViewModel调用对话框(InputDialog,ProgressDialog,MessageDialog甚至自己的CustomDialog),您只需要:
async void MyInputDialog()
{
await _dialogCoordinator.ShowInputAsync(this, "Dialog Title", "Dialog Message")
.ContinueWith(t => Console.WriteLine(t.Result));
}
答案 4 :(得分:0)
我猜PopupWindowAction
创建了一个窗口(其值为WindowContent
),因此您必须更改其实现或编写自己的实现。