我对在Prism中实现这一点感到困惑。我在一行中的场景是如何在主窗口上显示为单独的模态/非模态窗口的视图中实现Prism Navigation(regionManager.RequestNavigate)。
根据本文中的一些代码,我现在可以显示一个单独的窗口,但我对在所示窗口的区域中导航感到非常困惑。我将尝试在下面列出一些代码来澄清我的情况。
RoomBandViewModel中的此代码启动对话框
private void ManageRoomFacility() {
dialogService.ShowDialog<RoomFacilityMainWindowView>(this, container.Resolve<RoomFacilityMainWindowView>());
regionManager.RequestNavigate(RegionNames.Main_Region, new Uri("RoomFacilityMainView", UriKind.Relative));
可以看出,我启动了显示视图的对话框(代码如下所示),然后尝试在视图的某个区域中导航
弹出窗口RoomFacilityMainWindowView
<Window x:Class="HotelReservation.Main.View.RoomFacilities.RoomFacilityMainWindowView"
<view:RoomFacilityMainView
prism:RegionManager.RegionName="{x:Static const:RegionNames.Window_Main_Region}"/>
</Window>
窗口内的用户控制(RoomFacilityMainView)
<UserControl x:Class="HotelReservation.Main.View.RoomFacilities.RoomFacilityMainView"
<Grid VerticalAlignment="Stretch" >
...
<Border Grid.Column="0" Style="{StaticResource RegionBorderStyle}">
<StackPanel>
<TextBlock Text="Some Sample Text"/>
<ContentControl prism:RegionManager.RegionName="{x:Static const:RegionNames.Window_List_Region}"
/>
</StackPanel>
</Border>
<GridSplitter Width="5" Grid.Column="1" HorizontalAlignment="Stretch" />
<Border Grid.Column="2" Style="{StaticResource RegionBorderStyle}" >
<TabControl x:Name="Items" Margin="5" prism:RegionManager.RegionName="{x:Static const:RegionNames.Window_Edit_Region}" />
</Border>
</Grid>
</UserControl>
代码隐藏(RoomFacilityMainView.xaml.cs)
public partial class RoomFacilityMainView : UserControl {
public RoomFacilityMainView() {
InitializeComponent();
RoomFacilityMainViewModel viewModel = this.DataContext as RoomFacilityMainViewModel;
if (viewModel == null) {
viewModel = ServiceLocator.Current.GetInstance<RoomFacilityMainViewModel>();
this.DataContext = viewModel;
}
}
}
RoomFacilityMainViewModel公共类RoomFacilityMainViewModel:BindableBase{
IRegionManager regionManager;
IUnityContainer container;
public RoomFacilityMainViewModel(IRegionManager regionManager, IUnityContainer container) {
this.regionManager = regionManager;
this.container = container;
regionManager.RequestNavigate(RegionNames.Window_List_Region, new Uri("RoomFacilityListView", UriKind.Relative));
}
}
有了这个代码,就不会出现导航,我只得到一个空白窗口。RoomFacilityListView.xaml的Contents应该显示,但它为空。
如果代码令人困惑,那么请就如何使用View进行导航(使用RequestNavigate)提供建议,该View具有区域,但通过对话框服务显示为一个单独的窗口,而不是在MainWindow(Shell)上。
如果您使用的是通过Window.ShowDialog()
方法显示新窗口的IDialogService
实现,那么您的导航不起作用也就不足为奇了。ShowDialog()
方法仅在关闭窗口时返回,因此您的导航请求实际上将在关闭的窗口上处理,特别是在窗口关闭后的。
模态窗口中没有任何特殊情况会阻止使用Prism区域和其中的导航。一个限制是不能"按原样"创建多个窗口实例,因为它们都有相同名称的区域,而使用一个区域管理器是不可能的。然而,有一个解决方案:作用域区域管理器。
假设您不打算创建多个实例,下面是一个如何解决问题的示例。
首先,您必须确保模式对话框的RegionManager
与主RegionManager
是相同的实例(我在这里使用MEF,但实际上这无关紧要):
[Export]
public partial class Dialog : Window
{
private readonly IRegionManager rm;
[ImportingConstructor]
public Dialog(IRegionManager rm)
{
this.InitializeComponent();
this.rm = rm;
// Don't forget to set the attached property to the instance value
RegionManager.SetRegionManager(this, this.rm);
}
}
现在,使用一个接受导航回调的方法来扩展您的对话框服务实现:
bool? ShowDialog<T>(object ownerViewModel, object viewModel, Action initialNavigationCallback = null) where T : Window
{
Window dialog = /* your instance creation code, e.g. using container */;
dialog.Owner = FindOwnerWindow(ownerViewModel);
dialog.DataContext = viewModel;
if (initialNavigationCallback != null)
{
dialog.Loaded += (s, e) => initialNavigationCallback();
}
return dialog.ShowDialog();
}
这将为您提供一种显示带有初始导航请求的对话框的可能性,您可以将其称为:
void ManageRoomFacility() {
dialogService.ShowDialog<RoomFacilityMainWindowView>(
this,
container.Resolve<RoomFacilityMainWindowView>(),
() => regionManager.RequestNavigate(
RegionNames.Main_Region,
new Uri("RoomFacilityMainView", UriKind.Relative))
);
或者,您可以对任务使用基于状态的导航。在"基于状态的导航快速启动"中有一个发送消息模式对话框的示例实现。
<prism:InteractionRequestTrigger SourceObject="{Binding SendMessageRequest}">
<prism:PopupWindowAction IsModal="True">
<prism:PopupWindowAction.WindowContent>
<vs:SendMessagePopupView />
</prism: PopupWindowAction.WindowContent>
</prism:PopupWindowAction>
</prism:InteractionRequestTrigger>