我正在使用 PRISM/Unity 和 MVVM 方法开发 WPF 应用程序。到目前为止一切都很好,但我想我有一个概念上的问题。
因为我需要模态对话框,所以我实现了一个对话框服务,它被注入(inject)到 View 模型中,可以用来打开一个带有相应 View 的模态对话框。此对话框需要可导航( = 包含一个区域),以便我能够在对话框内切换 View 。为此,该服务创建一个窗口实例并导航到 DialogRegion 中请求的 View 。这也有效。
我现在的问题是,有时我需要打开第二个模态对话框,该对话框也需要可导航。如果我使用我的对话服务,我会得到对话窗口的一个新实例并抛出异常,因为该区域已经在区域管理器中注册(它在对话窗口的代码后面完成)。这是有道理的,因为 regionmanager 将无法区分区域,但会阻止我打开第二个可导航对话框。
什么是更好的方法?我只能考虑为该区域创建一个具有不同名称的第二个对话窗口,但这似乎是一个非常丑陋的解决方案......
编辑 1: 显示对话框的代码:
dialogService.ShowDialog<MyViewModel>();
对话框服务中显示对话框的代码:
public void ShowDialog<TDialogViewModel>() where TDialogViewModel : class
{
IModalDialog dialog = ServiceLocator.Current.TryResolve<IModalDialog>();
dialog.Owner = Application.Current.MainWindow;
regionManager.RequestNavigate(typeof(TDialogViewModel), Regions.DialogRegion);
dialog.ShowDialog();
}
对话窗口中的代码:
public DialogWindow(IRegionManager regionManager) : this()
{
RegionManager.SetRegionManager(this, regionManager);
this.regionManager = regionManager;
}
private void Window_Unloaded(object sender, RoutedEventArgs e)
{
regionManager.Regions.Remove(Regions.DialogRegion);
regionManager.Regions.Remove(Regions.DialogStatusRegion);
}
View 中用于构造、导航和显示其他对话框的代码
public MyViewModel(IRegionManager regionManager, IModalDialogService dialogService) : this()
{
this.regionManager = regionManager;
this.dialogService = dialogService;
}
void NavigateToSecondView()
{
regionManager.RequestNavigate<MyViewModel2>(Regions.DialogRegion);
}
void ShowDialog2()
{
// This is where a second dialog window with MyViewModel3 should be shown
dialogService.ShowDialog<MyViewModel3>();
}
编辑 2: 窗口的 XAML:
<Window.Resources>
<DataTemplate DataType="{x:Type localModels:MyViewModel}">
<localViewsProject:MyView/>
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Grid.Row="0" x:Name="DialogContent" Margin="10,10,10,10"
prismRegions:RegionManager.RegionName="{x:Static navi:Regions.DialogRegion}">
</ContentControl>
</Grid>
编辑 3 - IModalDialog 的代码: 我在网络上的某个地方得到了 IModalDialog 的想法,但我不记得在哪里。这个想法是有一个由一些窗口实例实现的接口(interface),并允许与用户交互。我的对话只有一个内容区域(加上状态/进度通知区域)可以通过 Prism 填充。
这里有一些代码来解释这个想法:
public partial class DialogWindow : Window, IModalDialog
{
internal IRegionManager regionManager;
public DialogWindow()
{
InitializeComponent();
}
public DialogWindow(IRegionManager regionManager)
: this()
{
RegionManager.SetRegionManager(this, regionManager);
this.regionManager = regionManager;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Load Model, when window is loaded
BaseViewModel model = this.DialogContent.Content as BaseViewModel;
if (model != null)
{
model.LoadData();
}
}
private void Window_Unloaded(object sender, RoutedEventArgs e)
{
regionManager.Regions.Remove(Regions.DialogRegion);
regionManager.Regions.Remove(Regions.DialogStatusRegion);
}
}
所以为了使用它,我有一个静态的 ModalDialogService,它接收一个模型和一些在对话框关闭后要完成的操作。像这样:
public void ShowDialog<TDialogViewModel>(Action<TDialogViewModel> initializeAction = null, Action<TDialogViewModel> actionAfterClose = null) where TDialogViewModel : class
{
IModalDialog dialog = ServiceLocator.Current.TryResolve<IModalDialog>();
if (actionAfterClose != null)
{
WeakEventManager<IModalDialog, EventArgs>.AddHandler(
dialog,
"Closed",
(sender, e) => dialogView_Closed(sender, e, typeof(TDialogViewModel), Regions.DialogRegion, actionAfterClose));
}
dialog.Owner = Application.Current.MainWindow;
regionManager.RequestNavigate(typeof(TDialogViewModel), Regions.DialogRegion);
TDialogViewModel model = null;
var region = regionManager.Regions[Regions.DialogRegion];
foreach (var view in region.ActiveViews)
{
if (view is TDialogViewModel)
{
model = (TDialogViewModel)view;
if (initializeAction != null)
{
initializeAction(model);
}
}
}
// Attach an event listener to the closing event in order to prevent closing
// if the form is not in a closeable state.
if (typeof(IConfirmNavigationRequest).IsAssignableFrom(typeof(TDialogViewModel)))
{
WeakEventManager<IModalDialog, CancelEventArgs>.AddHandler(
dialog,
"Closing",
(sender, e) => dialogView_Closing(sender, e, Regions.DialogRegion));
}
// This event can be published by a viewmodel in order to close the dialog
eventAggregator.GetEvent<DialogCloseRequestedEvent>().Subscribe((containingDialog) =>
{
if (containingDialog == model)
{
dialog.Close();
}
});
dialog.ShowDialog();
}
}
最佳答案
而不是用 RegionManager
重新注册一个 Region
。您可以重用已注册的初始 Region
并创建它的多个实例。这些被称为 Scoped Regions (在创建区域的多个实例部分下)。例如:
// You may need to keep track of these scopes
IRegionManager scopedRegionManager = _regionManager.Regions["DialogRegion"].Add(view, viewName, true);
scopedRegionManager.Navigate(viewName);
编辑
我相信这就像将 DialogWindow
的构造函数更改为这样简单:
public DialogWindow(IRegionManager regionManager) : this()
{
var scopedRegionManager = regionManager.Regions[Regions.DialogRegion].Add(this, null, true);
this.regionManager = scopedRegionManager;
}
关于c# - 使用 PRISM 与 WPF 应用程序中的区域对话,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23076316/