棱镜:不同用户控件之间的导航
Prism : Navigation between different Usercontrols
我正在使用棱镜。我有一个视图(DetailMainUC.xaml),它以下列方式包含许多其他视图。
<UserControl.Resources>
<DataTemplate x:Key="View1Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:HomeUC />
</DataTemplate>
<DataTemplate x:Key="View2Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:WalkAwayBehaviorUC />
</DataTemplate>
<DataTemplate x:Key="View3Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:WakeUpOnApproachUC />
</DataTemplate>
<DataTemplate x:Key="View4Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:NoLockOnPresenceUC />
</DataTemplate>
<DataTemplate x:Key="View5Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:PeekDimmingUC />
</DataTemplate>
<DataTemplate x:Key="View6Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:SettingsUC />
</DataTemplate>
</UserControl.Resources>
<Grid>
<ContentControl Grid.Column="1" Grid.Row="1" Content="{Binding }">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding SwitchView}" Value="Home">
<Setter Property="ContentTemplate" Value="{StaticResource View1Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding SwitchView}" Value="Walk Away Behaviour">
<Setter Property="ContentTemplate" Value="{StaticResource View2Template}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding SwitchView}" Value="Wake up on approach">
<Setter Property="ContentTemplate" Value="{StaticResource View3Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding SwitchView}" Value="No lock on presence">
<Setter Property="ContentTemplate" Value="{StaticResource View4Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding SwitchView}" Value="Peeking and Dimming">
<Setter Property="ContentTemplate" Value="{StaticResource View5Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding SwitchView}" Value="Settings">
<Setter Property="ContentTemplate" Value="{StaticResource View6Template}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
现在我正在使用事件聚合器在其他地区的不同视图模型之间进行通信。我的上述用户控件的视图模型如下:
public DetailMainUCViewModel(IEventAggregator eventAggregator, HomeViewModel homeViewModel)
{
this.HomeVM = homeViewModel;
this._eventAggregator = eventAggregator;
HomeVM.Initialization(this._eventAggregator);
this._eventAggregator.GetEvent<MenuClickEvent>().Subscribe(GetMenuName);
SwitchView = "Home";
}
现在 属性 HomeVM 是 HomeViewModel 类型,它是子 DetailMainUCViewModel 的视图模型。像这样还有很多其他的子视图模型。现在我的问题是我看到 HomeViewModel 的构造函数被调用了两次,所有其他子视图模型也发生了同样的情况。
我面临的主要问题是,当第二次调用子视图模型时,eventAggregator 变为空。
DetailsMainUCViewModel 是父视图模型,HomeViewModel 是子视图模型。 DetailMainUC.xaml 以代码部分中提到的方式保存 HomeUC.xaml 。
我也写了下面提到的代码
<UserControl.DataContext>
<vm:HomeViewModel></vm:HomeViewModel>
</UserControl.DataContext>
我怀疑是因为我使用了两个位置来附加数据上下文,所以我的视图模型被调用了两次。
在
1.HomeUC.xaml
2.Parent 用户控件 DetailMainUC.xaml
但我无法根据需要删除它们。
我的 class 设计是 DetailMainUCViewModel 是父视图模型,HomeViewModel 是子视图模型。 DetailMainUC.xaml 是父视图,HomeUC.xaml 是子视图。一开始我给出的代码片段来自 DetailMainUC.xaml(包含所有子用户控件)
除此之外,我正在我已实现 IModule 接口的模块中初始化我的 DetailMainUC.xaml。
public class STDetailOptionsModule : IModule
{
private readonly IRegionManager _regionManager;
public STDetailOptionsModule(IRegionManager regionManager)
{
this._regionManager = regionManager;
}
public void OnInitialized(IContainerProvider containerProvider)
{
_regionManager.RegisterViewWithRegion(RegionNames.DetailOptionsRegion, typeof(DetailMainUC));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
问候
如果我正确理解了您的问题,那么我可以说您在同一个用户控件中使用多个用户控件来通过触发器进行导航。
这种做法是不正确的。
基本上你想要在各种 usercontorls 之间导航。
让我解释一下如何在 Prism 中执行此操作。
this.regionManager.RequestNavigate("your region name where the usercontrol will be put ",
navigationPath, NavigationCompleted);
NavigationCompleted 是一个回调方法:
navigationPath: 是要放置在指定区域的用户控件路径。
希望清楚
你说你是新手,所以让我生动地解释一下。
据我所知,您有视图(WalkAwayBehaviorUC、WakeUpOnApproachUC、NoLockOnPresenceUC、PeekDimmingUC、SettingsUC)。
现在让我考虑这些视图在不同的项目中或在同一个项目中,但您希望它们显示在您所在的区域 RegionNames.DetailOptionsRegion。
现在要做到这一点,您必须将所有导航逻辑放在一个集中的位置。
最好的集中位置可能是 shell 。所以ShellViewModel.cs就是class你要写导航逻辑的地方。
所以创建一个这样的方法:
private void NavigationInitialized(string navigationPath)
{
if (string.IsNullOrEmpty(navigationPath))
{
throw new Exception();//or send proper message to UI
}
this.regionManager.RequestNavigate(RegionNames.DetailOptionsRegion,
navigationPath, NavigationCompleted);
}
private void NavigationCompleted(NavigationResult navigationResult)
{
}
现在的问题是如何在ShellViewModel.cs中获取这个导航名称。
解决方案是 EventAggregator.
在用户控件应该导航的地方写入。
this.eventAggregator.GetEvent<Navigated>().Publish("WalkAwayBehaviorUC");
现在 Navigated 事件 class 应该是这样的:
public class Navigated : PubSubEvent<string>
{
}
现在您必须在 ShellViewModel.cs
中订阅此导航事件
所以在 ShellViewModel.cs 的构造函数中你必须写:
this.eventAggregator.GetEvent<Navigated>().Subscribe(NavigationInitialized);
我正在使用棱镜。我有一个视图(DetailMainUC.xaml),它以下列方式包含许多其他视图。
<UserControl.Resources>
<DataTemplate x:Key="View1Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:HomeUC />
</DataTemplate>
<DataTemplate x:Key="View2Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:WalkAwayBehaviorUC />
</DataTemplate>
<DataTemplate x:Key="View3Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:WakeUpOnApproachUC />
</DataTemplate>
<DataTemplate x:Key="View4Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:NoLockOnPresenceUC />
</DataTemplate>
<DataTemplate x:Key="View5Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:PeekDimmingUC />
</DataTemplate>
<DataTemplate x:Key="View6Template" DataType="{x:Type vm:DetailMainUCViewModel}">
<local:SettingsUC />
</DataTemplate>
</UserControl.Resources>
<Grid>
<ContentControl Grid.Column="1" Grid.Row="1" Content="{Binding }">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding SwitchView}" Value="Home">
<Setter Property="ContentTemplate" Value="{StaticResource View1Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding SwitchView}" Value="Walk Away Behaviour">
<Setter Property="ContentTemplate" Value="{StaticResource View2Template}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding SwitchView}" Value="Wake up on approach">
<Setter Property="ContentTemplate" Value="{StaticResource View3Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding SwitchView}" Value="No lock on presence">
<Setter Property="ContentTemplate" Value="{StaticResource View4Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding SwitchView}" Value="Peeking and Dimming">
<Setter Property="ContentTemplate" Value="{StaticResource View5Template}" />
</DataTrigger>
<DataTrigger Binding="{Binding SwitchView}" Value="Settings">
<Setter Property="ContentTemplate" Value="{StaticResource View6Template}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Grid>
现在我正在使用事件聚合器在其他地区的不同视图模型之间进行通信。我的上述用户控件的视图模型如下:
public DetailMainUCViewModel(IEventAggregator eventAggregator, HomeViewModel homeViewModel)
{
this.HomeVM = homeViewModel;
this._eventAggregator = eventAggregator;
HomeVM.Initialization(this._eventAggregator);
this._eventAggregator.GetEvent<MenuClickEvent>().Subscribe(GetMenuName);
SwitchView = "Home";
}
现在 属性 HomeVM 是 HomeViewModel 类型,它是子 DetailMainUCViewModel 的视图模型。像这样还有很多其他的子视图模型。现在我的问题是我看到 HomeViewModel 的构造函数被调用了两次,所有其他子视图模型也发生了同样的情况。 我面临的主要问题是,当第二次调用子视图模型时,eventAggregator 变为空。
DetailsMainUCViewModel 是父视图模型,HomeViewModel 是子视图模型。 DetailMainUC.xaml 以代码部分中提到的方式保存 HomeUC.xaml 。 我也写了下面提到的代码
<UserControl.DataContext>
<vm:HomeViewModel></vm:HomeViewModel>
</UserControl.DataContext>
我怀疑是因为我使用了两个位置来附加数据上下文,所以我的视图模型被调用了两次。 在 1.HomeUC.xaml
2.Parent 用户控件 DetailMainUC.xaml
但我无法根据需要删除它们。 我的 class 设计是 DetailMainUCViewModel 是父视图模型,HomeViewModel 是子视图模型。 DetailMainUC.xaml 是父视图,HomeUC.xaml 是子视图。一开始我给出的代码片段来自 DetailMainUC.xaml(包含所有子用户控件)
除此之外,我正在我已实现 IModule 接口的模块中初始化我的 DetailMainUC.xaml。
public class STDetailOptionsModule : IModule
{
private readonly IRegionManager _regionManager;
public STDetailOptionsModule(IRegionManager regionManager)
{
this._regionManager = regionManager;
}
public void OnInitialized(IContainerProvider containerProvider)
{
_regionManager.RegisterViewWithRegion(RegionNames.DetailOptionsRegion, typeof(DetailMainUC));
}
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
问候
如果我正确理解了您的问题,那么我可以说您在同一个用户控件中使用多个用户控件来通过触发器进行导航。
这种做法是不正确的。 基本上你想要在各种 usercontorls 之间导航。
让我解释一下如何在 Prism 中执行此操作。
this.regionManager.RequestNavigate("your region name where the usercontrol will be put ",
navigationPath, NavigationCompleted);
NavigationCompleted 是一个回调方法: navigationPath: 是要放置在指定区域的用户控件路径。
希望清楚
你说你是新手,所以让我生动地解释一下。
据我所知,您有视图(WalkAwayBehaviorUC、WakeUpOnApproachUC、NoLockOnPresenceUC、PeekDimmingUC、SettingsUC)。 现在让我考虑这些视图在不同的项目中或在同一个项目中,但您希望它们显示在您所在的区域 RegionNames.DetailOptionsRegion。
现在要做到这一点,您必须将所有导航逻辑放在一个集中的位置。 最好的集中位置可能是 shell 。所以ShellViewModel.cs就是class你要写导航逻辑的地方。
所以创建一个这样的方法:
private void NavigationInitialized(string navigationPath)
{
if (string.IsNullOrEmpty(navigationPath))
{
throw new Exception();//or send proper message to UI
}
this.regionManager.RequestNavigate(RegionNames.DetailOptionsRegion,
navigationPath, NavigationCompleted);
}
private void NavigationCompleted(NavigationResult navigationResult)
{
}
现在的问题是如何在ShellViewModel.cs中获取这个导航名称。 解决方案是 EventAggregator.
在用户控件应该导航的地方写入。
this.eventAggregator.GetEvent<Navigated>().Publish("WalkAwayBehaviorUC");
现在 Navigated 事件 class 应该是这样的:
public class Navigated : PubSubEvent<string>
{
}
现在您必须在 ShellViewModel.cs
中订阅此导航事件所以在 ShellViewModel.cs 的构造函数中你必须写:
this.eventAggregator.GetEvent<Navigated>().Subscribe(NavigationInitialized);