Xamarin.Forms: ViewModel страницы с вкладками не вызывается с помощью Autofac - PullRequest
0 голосов
/ 13 июня 2019

Я использую Autofac версии 4.9.2 в моем приложении.Ниже приведена последовательность навигации:

SplashView->LoginView->MainView

MainView - страница с вкладками, содержащая меню с 4 вкладками.При нажатии на каждый пункт меню вызывается соответствующая страница, но ее ViewModel не вызывается.

Я зарегистрировал каждый класс ViewModel в классе Locator, а также добавил отображение каждой 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();

}

Класс NavigationService:

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));
    }
}

MainView 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>

LoginViewModel:

После успешного входа в систему:

await NavigationService.NavigateToAsync<MainViewModel>();
...