首页 > 解决方案 > 从 Xamarin 表单的 Prism 中的模块导航后“具有给定名称的区域已注册”

问题描述

(我只想说我有一个解决方法,使用EventAggregator- 如帖子底部所示 - 但我想深入了解为什么它不能按照我目前设置的方式工作)。

我有一个 Xamarin Forms 应用程序,我在其中使用 Prism(版本 8)作为 Xamarin Forms(版本 4.8)。在这个应用程序中,我使用表单的模块和区域。

我的主要应用程序有一个MainPage(在 a 中NavigationPage),其中我有一个 Prism 区域,视图被注入其中。

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="TestPrismModules.Views.MainPage"
             xmlns:prism="http://prismlibrary.com"
             prism:ViewModelLocator.AutowireViewModel="True"
             Title="{Binding Title}">

            <StackLayout Orientation="Vertical">
                    <FlexLayout prism:RegionManager.RegionName="FlexRegion"/>
            </StackLayout>
</ContentPage>

我有一个模块 (AuthModule),它通过AuthenticationService. 该模块还包含一个LoginPagewith equivelant LoginPageViewModel。中的Logout方法AuthenticationService执行注销NavigateAsync并对LoginPage

public class AuthenticationService : IAuthenticationService
{
    private readonly INavigationService _navigationService;

    public AuthenticationService(INavigationService navigationService)
    {
        _navigationService = navigationService;
    }

    public void Logout()
    {
        // logging out code goes here
        _navigationService.NavigateAsync("/LoginPage");
    }
}

这是 AuthModule 模块代码:

public class AuthModuleModule : IModule
{
    public void OnInitialized(IContainerProvider containerProvider)
    {
    }

    public void RegisterTypes(IContainerRegistry containerRegistry)
    {
        containerRegistry.Register<IAuthenticationService, AuthenticationService>();
        containerRegistry.RegisterRegionServices();
        containerRegistry.RegisterForNavigation<LoginPage, LoginPageViewModel>();
    }
}

启动应用程序后,导航到的第一个页面是LoginPage(提醒 - 在 AuthModule 中)。到目前为止,一切都很好。

我有一个要求,如果用户暂时停用应用程序,一旦它恢复或重新激活,用户就会注销并必须再次登录。为此,我重写了该OnResume方法,解析了 my 的一个实例AuthenticationService并在其中调用了该Logout方法。

public partial class App
{
    public App(IPlatformInitializer initializer)
        : base(initializer)
    {
    }

    protected override async void OnInitialized()
    {
        InitializeComponent();
        var ea = Container.Resolve<IEventAggregator>();
        ea.GetEvent<LoggedInEvent>().Subscribe(OnUserAuthenticated);
        await NavigationService.NavigateAsync("/LoginPage",null,true,true);
    }

    private void OnUserAuthenticated()
    {
        NavigationService.NavigateAsync("/NavigationPage/MainPage");
    }

    protected override void RegisterTypes(IContainerRegistry containerRegistry)
    {

        containerRegistry.RegisterRegionServices();
        containerRegistry.RegisterSingleton<IAppInfo, AppInfoImplementation>();

        containerRegistry.RegisterForNavigation<NavigationPage>();
        containerRegistry.RegisterForNavigation<MainPage, MainPageViewModel>();
        
    }

    protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
    {
        base.ConfigureModuleCatalog(moduleCatalog);
        moduleCatalog.AddModule<TestModule1Module>();
        moduleCatalog.AddModule<AuthModuleModule>();
    }


    // Want to force user to login when the app resumes
    protected override void OnResume()
    {
        base.OnResume();

        // Logout and redirect to Login Page
        var authService = Container.Resolve<IAuthenticationService>();
        authService.Logout();
    }
 }

这一切都很好而且花花公子 - 直到用户尝试再次登录并且他们得到可怕的“具有给定名称的区域已经注册

LoginPage直接从主应用程序导航到(而不是通过AuthenticationService),并在MainPage重新登录后返回到 ,工作正常,我没有得到关于 Region 已经注册的异常。知道了这一点,我有一个解决方法,我使用EventAggregator订阅LoggedOut事件(在 中App.xaml.cs)并从 发布该事件并从订阅中AuthenticationService调用NavigateAsync

我怀疑我可能会收到有关使用 Scoped 区域或类似区域的建议,但我不确定如何去做。

我在这里有一个示例项目来测试它是否有帮助:https ://github.com/tomaswinston/TestPrismModulesAuth

标签: xamarin.formsprismregion

解决方案


推荐阅读