首页 > 解决方案 > 棱镜:不同用户控件之间的导航

问题描述

我正在使用棱镜。我有一个视图(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.父用户控件DetailMainUC.xaml

但是我无法根据需要删除它们。我的课程设计是 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)
    {

    }
}

问候

标签: wpfmvvmprism

解决方案


如果我正确理解了您的问题,那么我可以说您在同一个用户控件中使用多个用户控件通过触发器进行导航。

这种方法是不正确的。基本上,您想要在各种用户控件之间进行导航。

让我解释一下如何在 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 是你必须编写导航逻辑的类。

所以创建一个这样的方法:

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");

现在导航事件类应该是这样的:

public class Navigated : PubSubEvent<string>
{
}

现在您必须在 ShellViewModel.cs 中订阅此导航事件

因此,在 ShellViewModel.cs 的构造函数中,您必须编写:

this.eventAggregator.GetEvent<Navigated>().Subscribe(NavigationInitialized);

推荐阅读