导航到模块中的视图时不调用 OnNavigatedTo

Posted

技术标签:

【中文标题】导航到模块中的视图时不调用 OnNavigatedTo【英文标题】:OnNavigatedTo is not invoked when navigating to a view in module 【发布时间】:2021-06-11 12:14:59 【问题描述】:

我是 Prism 新手,正在尝试用它制作一个简单的模块化应用程序(请参阅 full code)。

我实际上是在尝试将参数传递给视图,所以在ModuleAViewModuleAViewViewModel 中我正在实现INavigationAware,这样:

public class ModuleAViewViewModel : BindableBase, INavigationAware

    private int passedId;

    public int PassedId
    
        get => passedId;
        set => SetProperty(ref passedId, value);
    

    // In the following 3 methods, a breakpoint never gets hit.

    public bool IsNavigationTarget(NavigationContext navigationContext)
    
        return true;
    

    public void OnNavigatedFrom(NavigationContext navigationContext)
    
    

    public void OnNavigatedTo(NavigationContext navigationContext)
    
        PassedId = (int)navigationContext.Parameters["Id"];
    

这是对应的ModuleAView

<UserControl x:Class="ModularSample1.Modules.ModuleA.Views.ModuleAView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ModularSample1.Modules.ModuleA.Views"
             xmlns:viewmodels="clr-namespace:ModularSample1.Modules.ModuleA.ViewModels"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>
        <viewmodels:ModuleAViewViewModel x:Key="moduleAViewModel"/>
    </UserControl.Resources>
    <Grid DataContext="StaticResource moduleAViewModel">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock 
            Grid.Row="1"
            Text="Binding PassedId, StringFormat='Passed Id: 0'"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            FontSize="34"/>
    </Grid>
</UserControl>

实际导航到该视图的 ViewModel 如下所示:

public class MainWindowViewModel : BindableBase

    private readonly IRegionManager regionManager;

    public MainWindowViewModel(IRegionManager regionManager, IModuleManager moduleManager)
    
        this.regionManager = regionManager;

        moduleManager.Run();
        Modules = moduleManager.Modules.ToList();
    

    private List<IModuleInfo> modules;
    private IModuleInfo selectedModule;

    public List<IModuleInfo> Modules
    
        get => modules;
        set => SetProperty(ref modules, value);
    

    public IModuleInfo SelectedModule
    
        get => selectedModule;
        set
        
            if (SetProperty(ref selectedModule, value))
            
                var Id = new Random().Next(1, 12);
                var navigationParameters = new NavigationParameters
                
                     "Id", Id 
                ;

                regionManager.RequestNavigate(
                    "SelectedModuleRegion",
                    $"selectedModule.ModuleNameView",
                    navigationParameters);
            
        
    

我在这里缺少什么?

【问题讨论】:

【参考方案1】:

您在 Resources 中为 ModuleAView 定义视图模型,并通过引用将其设置在子 Grid 上。 Prism 会在 视图本身 上查找 DataContext 以调用实现 INavigationAware 的视图模型,而不是子控件,因此它找不到您的视图模型。来自文档:

在导航期间,Prism 会检查视图是否实现了INavigationAware 接口;如果是这样,它会在导航期间调用所需的方法。 Prism 还会检查设置为视图的DataContext 的对象是否实现了该接口;如果是,它会在导航期间调用所需的方法。

为了使其工作,直接在ModuleAView 上设置数据上下文并将其从Grid 中删除。

<UserControl x:Class="ModularSample1.Modules.ModuleA.Views.ModuleAView"
             ...>
    <UserControl.DataContext>
        <viewmodels:ModuleAViewViewModel/>
    </UserControl.DataContext>
    <Grid>
        <!-- ...grid definitions. -->
    </Grid>
</UserControl>

更好的替代方法是从您的ModuleAView 中完全删除手动设置数据上下文,并直接使用ModuleAViewViewModel 注册您的ModuleAView。 Prism 的导航服务将在导航期间自动解析视图模型并将其分配为数据上下文。

containerRegistry.RegisterForNavigation<ModuleAView, ModuleAViewViewModel>();

您甚至可以通过遵循关于 ViewModelLocator 的视图和视图模型的命名约定来简化这一点,这将用于导航以解析视图的视图模型。

ViewModel 与视图类型在同一个程序集中 ViewModel 位于 .ViewModels 子命名空间中 视图位于 .Views 子命名空间中 ViewModel 名称与视图名称相对应,并以“ViewModel.”结尾

您违反了最后一条规则,因此将ModuleAViewViewModel 重命名为ModuleAViewModel 并仅删除数据上下文的手动设置将使Prism 能够自动为您在RegisterForNavigation 注册的视图找到相应的视图模型。

containerRegistry.RegisterForNavigation<ModuleAView>();

【讨论】:

以上是关于导航到模块中的视图时不调用 OnNavigatedTo的主要内容,如果未能解决你的问题,请参考以下文章

视图中的 UITapGesture 时不调用 UIButton 操作

UINavigationContoller interactivePopGestureRecognizer 在导航栏隐藏时不活动

在 UINavigationController 中隐藏导航栏时不向后滑动

从 iOS 11 搜索控制器导航时不需要的 UITableView 重新加载动画

无法导航到根视图控制器

如何修复表视图单元格在启动时不显示?