Mvvmcross中的View Model初始化导航不起作用。

4

我有一个登录视图和另一个在登录后显示的视图。我正在使用MvvmCross与本机Xamarin.Android和Xamarin.iOS。

因此,我有2个视图模型,LoginViewModel和MenuViewModel。我像这样注册appstart:

RegisterAppStart<LoginViewModel>(); 

在LoginViewModel中,我检查用户是否已经登录。 如果已登录,我想要导航到MenuViewModel并停止显示LoginViewModel。
public override async Task Initialize()
{
    await base.Initialize();
    await AppConfig.Initialize();

    bool isLoggedIn = _authService.IsUserLoggedIn();
    if (isLoggedIn)
    {
        await _navigationService.Navigate<NavControllerViewModel>();
        await _navigationService.Close(this);
    }            
}

上述代码不起作用,LoginView被显示而不是MenuView。尽管如此,当LoginView完全加载并且用户与之交互后,导航确实起作用。因此,我有一个登录用户的命令LoginCommand,它会登录用户,并且如果此操作成功,则导航到MenuViewModel。类似于:

 private async Task Login()
 {
    if (!string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(Password))
    {
        if (Validations.IsValidEmail(Username))
        {
            OAuthResponse response = await UserController.Instance.Login(Username, Password);

            if (response.Error != null)
            {
                //Login NOk
                Mvx.IoCProvider.Resolve<IUserDialogs>().Alert(response.Error.Msg);
            }
            else
            {
                //Login OK
                ShowMenuScreenCommand.Execute(null);
            }
        }
        else
        {
            Mvx.IoCProvider.Resolve<IUserDialogs>().Alert("LoginView_Alert_InvalidEmail".Translate());
        }
    }
    else
    {
        Mvx.IoCProvider.Resolve<IUserDialogs>().Alert("LoginView_Alert_MissingRequiredFields".Translate());
    }
}

定义ShowMenuScreenCommand如下:

public IMvxAsyncCommand ShowMenuScreenCommand
{
    get
    {
        _navigateCommand = _navigateCommand ?? new MvxAsyncCommand(async () => await _navigationService.Navigate<NavControllerViewModel>());
        return _navigateCommand;
    }
}

为什么Initialize()方法中的导航不起作用?

可能是视图模型的Initialize()方法不是执行此导航的好时机吗?

我尝试将IsUserLogedIn逻辑放入视图生命周期的其他方法中,如ViewAppearing(),ViewAppeared()等,但没有成功。

谢谢!


2
那也是一个很愚蠢的导航位置。初始化并不能保证视图已经出现。所以你可能会在另一个导航请求的中间尝试导航。ViewAppeared 将是一个更好的地方来做这件事。然而,这意味着当前的 ViewModel 将被显示。你应该在导航到你的 IsLoggedIn 检查的 ViewModel 之前进行检查。 - Cheesebaron
可能是MVVMCross程序化更改起始ViewModel的重复问题。 - jotade
@jotade 我不这么认为。我不想改变起始视图模型。我想从初始化方法导航到另一个视图控制器。正如指出的那样,这不是一个好的做法,所以我改变了我的应用程序中导航的概念。 - jcasas
感谢@Cheesebaron提供的信息,非常有帮助。 - jcasas
1个回答

2

不要使用RegisterAppStart<LoginViewModel>();

你可以注册自己的MvxAppStart,并从那里检查用户是否已登录,并直接进入你的NavControllerViewModel,否则进入LoginViewModel。你甚至可以在构造函数中注入你的身份验证服务。

创建你的MvxAppStart

public class AppStart : MvxAppStart
{
    private readonly IMvxNavigationService _navigationService;
    private readonly IAuthenticationService _authService;

    public AppStart(
        IMvxApplication application,
        IMvxNavigationService navigationService,
        IAuthenticationService authService)
        : base(application, navigationService)
    {
        _navigationService = navigationService ?? throw new ArgumentNullException(nameof(navigationService));
        _authService = authService ?? throw new ArgumentNullException(nameof(authService));
    }

    protected override async Task NavigateToFirstViewModel(object hint = null)
    {
        var isUserLoggedIn = _authService.IsUserLoggedIn();

        if (isUserLoggedIn)
        {
            await _navigationService.Navigate<NavControllerViewModel>();
        }
        else
        {
            await _navigationService.Navigate<LoginViewModel>();
        }
    }
}

Register your MvxAppStart

public class App : MvxApplication
{
    public override void Initialize()
    {
        RegisterCustomAppStart<AppStart>();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接