首页 > 解决方案 > Xamarin.Forms:未使用 Autofac 调用选项卡式页面的 ViewModel

问题描述

我在我的应用程序中使用Autofac 4.9.2 版。以下是导航顺序:

SplashView->LoginView->MainView

MainView 是包含 4 个选项卡菜单的选项卡式页面。在点击每个菜单项时,都会调用相应的页面,但不会调用它的 ViewModel。

我已经在 Locator 类中注册了每个 ViewModel 类,并且还添加了每个 ViewModel 相对于它的 View 的映射。

定位器类

public class Locator
{
    IContainer container;
    ContainerBuilder containerBuilder;

    public static Locator Instance { get; } = new Locator();

    public Locator()
    {
        containerBuilder = new ContainerBuilder();

        containerBuilder.RegisterType<NavigationService>().As<INavigationService>();
        containerBuilder.RegisterType<RequestService>().As<IRequestService>();


        containerBuilder.RegisterType<SplashViewModel>();
        containerBuilder.RegisterType<LoginViewModel>();
        containerBuilder.RegisterType<MainViewModel>();
        containerBuilder.RegisterType<Tab1ViewModel>();
        containerBuilder.RegisterType<Tab2ViewModel>();
        containerBuilder.RegisterType<Tab3ViewModel>();
        containerBuilder.RegisterType<Tab4ViewModel>();

    }

    public T Resolve<T>() => container.Resolve<T>();

    public object Resolve(Type type) => container.Resolve(type);

    public void Register<TInterface, TImplementation>() where TImplementation : TInterface => containerBuilder.RegisterType<TImplementation>().As<TInterface>();

    public void Register<T>() where T : class => containerBuilder.RegisterType<T>();

    public void Build() => container = containerBuilder.Build();

}

导航服务类:

public class NavigationService : INavigationService
{
    readonly IAuthenticationService authenticationService;
    protected readonly Dictionary<Type, Type> mappings;

    protected Application CurrentApplication => Application.Current;

    public NavigationService()
    {
        mappings = new Dictionary<Type, Type>();
        CreatePageViewModelMappings();
    }

    public async Task InitializeAsync()
    {
        await NavigateToAsync<LoginViewModel>();
    }

    public async Task NavigateBackAsync()
    {
        if (CurrentApplication.MainPage is MainView)
        {
            var mainPage = CurrentApplication.MainPage as MainView;
            await mainPage.Navigation.PopAsync();
        }
        else if (CurrentApplication.MainPage != null)
        {
            await CurrentApplication.MainPage.Navigation.PopAsync();
        }
    }

    public Task NavigateToAsync<TViewModel>() where TViewModel : ViewModelBase=> InternalNavigateToAsync(typeof(TViewModel), null);

    public Task NavigateToAsync<TViewModel>(object parameter) where TViewModel : ViewModelBase=> InternalNavigateToAsync(typeof(TViewModel), parameter);

    public Task NavigateToAsync(Type viewModelType) => InternalNavigateToAsync(viewModelType, null);

    public Task NavigateToAsync(Type viewModelType, object parameter) => InternalNavigateToAsync(viewModelType, parameter);

    public virtual Task RemoveLastFromBackStackAsync()
    {
        if (CurrentApplication.MainPage is MainView mainPage)
        {
            mainPage.Navigation.RemovePage(
                mainPage.Navigation.NavigationStack[mainPage.Navigation.NavigationStack.Count - 2]);
        }

        return Task.FromResult(true);
    }

    protected Page CreateAndBindPage(Type viewModelType, object parameter)
    {
        var pageType = GetPageTypeForViewModel(viewModelType);

        if (pageType == null)
        {
            throw new Exception($"Mapping type for {viewModelType} is not a page");
        }

        var page = Activator.CreateInstance(pageType) as Page;
        var viewModel = Locator.Instance.Resolve(viewModelType) as ViewModelBase;
        page.BindingContext = viewModel;

        return page;
    }

    void CreatePageViewModelMappings()
    {
        mappings.Add(typeof(SplashViewModel), typeof(SplashView));
        mappings.Add(typeof(LoginViewModel), typeof(LoginView));
        mappings.Add(typeof(MainViewModel), typeof(MainView));
        mappings.Add(typeof(Tab1ViewModel), typeof(Tab1View));
        mappings.Add(typeof(Tab2ViewModel), typeof(Tab2View));
        mappings.Add(typeof(Tab3ViewModel), typeof(Tab3View));
        mappings.Add(typeof(Tab4ViewModel), typeof(Tab4View));
    }
}

主视图 xaml:

<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" 
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
            xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
            xmlns:page="clr-namespace:SampleApp.Views;assembly=SampleApp"
            x:Class="SampleApp.Views.MainView">

        <page:Tab1View Title="Tab1" Icon="tab1.png"/>
        <page:Tab2View Title="Tab2" Icon="tab2.png"/>
        <page:Tab3View Title="Tab3" Icon="tab3.png"/>
        <page:Tab4View Title="Tab4" Icon="tab4.png"/>

</TabbedPage>

登录视图模型:

登录成功后:

await NavigationService.NavigateToAsync<MainViewModel>();

标签: c#xamarinmvvmxamarin.formsautofac

解决方案


推荐阅读