【问题标题】:Upgrade to Prism 8 is causing navigation errors升级到 Prism 8 导致导航错误
【发布时间】:2021-03-21 23:07:08
【问题描述】:

环境

  • Xamarin 表单:5.0.0.1709-pre4(但也会因 4.8.0.1687 而失败)
  • VS2019 16.8.3
  • X 代码:12.2

Prism NuGet

  • Prism.DryIoc.Extensions 8.0.48
  • Prism.Forms 8.0.0.1909
  • Prism.PluginPopups 8.0.31-beta
  • Shiny.Prism 8.0.48

INavigationResult 的内部异常:DryIoc.ContainerException -> InvalidOperationException

    code: Error.UnableToResolveFromRegisteredServices;
    message: Unable to resolve Resolution root IRMobile.PageModels.LandingPageModel with passed arguments 
    [Constant(Prism.Navigation.ErrorReportingNavigationService, 
    typeof(Prism.Navigation.ErrorReportingNavigationService))]
      from container with scope {Name=null}
     with Rules with {TrackingDisposableTransients, UseDynamicRegistrationsAsFallbackOnly, 
    FuncAndLazyWithoutRegistration, SelectLastRegisteredFactory} and without 
    {ThrowOnRegisteringDisposableTransient, UseFastExpressionCompilerIfPlatformSupported}
     with FactorySelector=SelectLastRegisteredFactory
     with Made={FactoryMethod=ConstructorWithResolvableArguments}
      with normal and dynamic registrations:
      (DefaultDynamicKey(0), {FactoryID=317, ImplType=IRMobile.PageModels.LandingPageModel, 
    Reuse=TransientReuse, HasCondition})

来自 InnerException 的堆栈跟踪:

  at DryIoc.Container.TryThrowUnableToResolve (DryIoc.Request request) [0x00058] in /_/src/DryIoc/Container.cs:1077 
  at DryIoc.Container.DryIoc.IContainer.ResolveFactory (DryIoc.Request request) [0x00072] in /_/src/DryIoc/Container.cs:1059 
  at DryIoc.Container.ResolveAndCacheKeyed (System.Int32 serviceTypeHash, System.Type serviceType, System.Object serviceKey, DryIoc.IfUnresolved ifUnresolved, System.Object scopeName, System.Type requiredServiceType, DryIoc.Request preResolveParent, System.Object[] args) [0x000c5] in /_/src/DryIoc/Container.cs:471 
  at DryIoc.Container.DryIoc.IResolver.Resolve (System.Type serviceType, System.Object serviceKey, DryIoc.IfUnresolved ifUnresolved, System.Type requiredServiceType, DryIoc.Request preResolveParent, System.Object[] args) [0x00042] in /_/src/DryIoc/Container.cs:430 
  at DryIoc.Resolver.Resolve (DryIoc.IResolver resolver, System.Type serviceType, System.Object[] args, DryIoc.IfUnresolved ifUnresolved, System.Type requiredServiceType, System.Object serviceKey) [0x00000] in /_/src/DryIoc/Container.cs:7809 
  at Prism.DryIoc.DryIocContainerExtension.Resolve (System.Type type, System.ValueTuple`2[System.Type,System.Object][] parameters) [0x0001c] in /_/external/Prism/src/Containers/Prism.DryIoc.Shared/DryIocContainerExtension.cs:294 

App.xaml.cs

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            // for RgPopups
            containerRegistry.RegisterPopupNavigationService();
            containerRegistry.RegisterPopupDialogService();

            // Essentials
            containerRegistry.Register<ISecureStorage, SecureStorageImplementation>();
            containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>();

            // page stuff
            containerRegistry.RegisterForNavigation<NavigationPage>();
            containerRegistry.RegisterForNavigation<IconNavigationPage>();
            containerRegistry.RegisterSingleton<IPageBehaviorFactory, CustomPageBehaviorFactory>();

            ...
            // Page and model registrations
containerRegistry.RegisterForNavigation<LoginPage, LoginPageModel>();
            containerRegistry.RegisterForNavigation<LandingPage, LandingPageModel>();

        }

我在尝试从 LoginPage 导航到根主/详细信息页面时遇到此异常

await NavigationService.NavigateAsync("/MainPage/NavigationPage/LandingPage")

LandingPage 的构造函数是

public LandingPageModel(INavigationService navigationService, IMapper mapper, IDialogs dialogs, IPushManager pushManager) : base(navigationService, mapper)

我对 Prism 还很陌生,所以我确定我缺少一些东西,一个注册或者一个 NuGet 包,但我不确定它会是什么。当我遇到同样的错误时,我注释掉了弹出窗口的注册,但指的是Prism.Plugin.Popups.PopupPageNavigationService

一如既往,感谢您的帮助!

【问题讨论】:

    标签: xamarin.forms prism


    【解决方案1】:

    您似乎正在尝试导航到名为 LandingPage 的页面,但您尚未告诉容器 LandingPage 是什么。

    每次您想要创建一个新视图并导航到它时,您都需要在您的 App.Xaml.cs 文件中为 Navigation 注册它;

    containerRegistry.RegisterForNavigation<LandingPage, LandingPageViewModel>();
    

    这一行在容器内注册了视图及其对应的 ViewModel。一旦容器知道视图,NavigationService 就可以使用视图的文字名称 LandingPage 解析您希望导航到的视图。

    现在你可以打电话了

    await NavigationService.NavigateAsync("LandingPage");
    //or
    await NavigationService.NavigateAsync("/MainPage/NavigationPage/LandingPage")
    

    注意

    Prism 导航内置了一些巧妙的技巧。它是基于 Uri 的,因此每次导航到另一个视图时,在 NavigateAsync 方法中传递视图的名称会将视图堆叠在其他视图之上。这意味着,如果你从 URI NavigationPage/PageA 开始,然后你说 NavigateAsync("PageB"),你将在 NavigationPage/PageA/PageB 结束。

    此外,在 NavigateAsync 参数的开头包含 / 字符会完全重置堆栈。因此,如果您从 NavigationPage/PageA/PageB 导航到 /PageC,这会将堆栈重置为 PageC

    【讨论】:

    • 对不起,需要更新描述,“...”是所有页面注册的地方。因此,Landing page 和 LandingPageModel 是真正注册的。
    • 在导航之前,将 NavigateAsync 的结果赋值给一个变量,看看 NavigationResult 是什么。如果为假,您应该能够查看内部异常,以便更好地诊断原因。 IDialogs 到底是什么?我没有看到它在容器内注册。此外,我将向您介绍您的命名约定。 LandingPageModel 应该真正称为 LandingPageViewModel。模型是您通过视图模型与之交互的类
    • 是的,上面的例外来自该导航的 INavigationResult。我添加了异常类型和堆栈跟踪。回复:命名约定,这是从 FreshMVVM(超过 100 页)的迁移,所以现在,由于容器注册允许,我们保持“PageModel”命名约定。以后可能会重构。
    • 将 INavigationAware 添加到您要导航到的页面,查看该页面是否真正开始导航过程
    • 我有 INavigatedAware,将其切换到 INavigationAware 并在导航后出现同样的异常。奇怪的是,它导航到登录页面就好了,那是 App.xaml.cs 的初始导航
    猜你喜欢
    • 2023-02-07
    • 2013-06-12
    • 1970-01-01
    • 2021-01-24
    • 2020-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多