我正在使用PRISM / Unity和MVVM方法开发WPF应用程序。到目前为止一切都很好,但我认为我有一个概念问题。
由于我需要模态对话框,我实现了一个对话服务,它被注入到视图模型中,可以用来打开一个带有相应视图的模态对话框。此对话框需要可导航(=包含区域),以便我能够在对话框中切换视图。为此,服务创建窗口的实例并导航到DialogRegion中的请求视图。这也有效。
我现在的问题是,在某些时候我需要打开第二个模态对话框,该对话框也需要可导航。如果我使用我的对话服务,我会得到一个对话窗口的新实例,并抛出一个异常,因为该区域已经注册了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);
}
构建,导航和显示其他对话框视图中的代码
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的想法,但我不记得在哪里。我们的想法是拥有一个由一些窗口实例实现的接口,并允许与用户进行交互。我的对话框只有一个内容区域(加上状态/进度通知区域),可以通过棱镜填充。
这里有一些代码来解释这个想法:
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();
}
}
答案 0 :(得分:0)
而不是使用Region
重新注册RegionManager
。您可以重用已注册的初始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;
}