Как вставить стек навигации на страницу с вкладками - PullRequest
0 голосов
/ 15 февраля 2019

Я использую MvvmCross и Xamarin Forms.Главная страница моего приложения - MvxTabbedPage с четырьмя вкладками.Каждая из вкладок - это страницы навигации, которые содержат свои собственные страницы содержимого.Независимо от того, какая вкладка является текущей, любой Navigate вызов IMvxNavigationService помещает страницу на первую вкладку.

Распечатка Application.Current.Hierarchy() выглядит следующим образом:

Application Root
 HomePage(Tabbed)
        [0]: MvxNavigationPage(Navigation)
                          [0]: FirstPage(Content)
        [1]: MvxNavigationPage(Navigation)
                          [0]: SecondPage(Content)
        [2]: MvxNavigationPage(Navigation)
                          [0]: ThirdPage(Content)
        [3]: MvxNavigationPage(Navigation)
                          [0]: FourthPage(Content)

ИнициированиеNavigate до DetailsPage из второй вкладки приводит к этой иерархии:

Application Root
 HomePage(Tabbed)
        [0]: MvxNavigationPage(Navigation)
                          [0]: FirstPage(Content)
                          [1]: DetailsPage(Content)
        [1]: MvxNavigationPage(Navigation)
                          [0]: SecondPage(Content)
        [2]: MvxNavigationPage(Navigation)
                          [0]: ThirdPage(Content)
        [3]: MvxNavigationPage(Navigation)
                          [0]: FourthPage(Content)

В попытке отладки я прикрепил обработчик к событию CurrentPageChanged на моем MvxTabbedPage, и я могу подтвердить, чтоCurrentPage обновлен правильно.Я также попробовал настройки WrapInNavigationPage = true для TabbedPage, но это привело к нежелательному поведению при навигации.

HomePage.xaml (без кода):

<?xml version="1.0" encoding="UTF-8"?>
<views:MvxTabbedPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:views="clr-namespace:MvvmCross.Forms.Views;assembly=MvvmCross.Forms"
    xmlns:mvx="clr-namespace:MvvmCross.Forms.Bindings;assembly=MvvmCross.Forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:Ketchup.Core.Views"
    xmlns:viewModels="clr-namespace:Ketchup.Core.ViewModels;assembly=Ketchup.Core" 
    x:Class="Ketchup.Core.Views.HomePage"
    x:TypeArguments="viewModels:HomeViewModel" 
    ItemTemplate="{mvx:MvxBind DataTemplateSelector}"
    ItemsSource="{mvx:MvxBind TabViewModels}"
    xmlns:android="clr-namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
    android:TabbedPage.ToolbarPlacement="Bottom"
    >

</views:MvxTabbedPage>

HomePageViewModel.cs

    public class HomeViewModel : MvxViewModel
    {
        // Bound Property
        List<IMvxViewModel> _tabViewModels;
        public List<IMvxViewModel> TabViewModels
        {
            get
            {
                return _tabViewModels;
            }
            set
            {
                _tabViewModels = value;
                RaisePropertyChanged(() => TabViewModels);
            }
        }
        // Bound Property
        public TabDataTemplateSelector DataTemplateSelector
        {
            get;
            set;
        }
        // ...

        public class TabDataTemplateSelector : DataTemplateSelector
        {

            private IMvxViewsContainer _viewsContainer;
            protected IMvxViewsContainer ViewsContainer
            {
                get
                {
                    if (_viewsContainer == null)
                        _viewsContainer = Mvx.IoCProvider.Resolve<IMvxViewsContainer>();
                    return _viewsContainer;
                }
            }

            Dictionary<IMvxViewModel, DataTemplate> Cache;

            public TabDataTemplateSelector()
            {

                Cache = new Dictionary<IMvxViewModel, DataTemplate>();

            }

            protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
            {

                Console.WriteLine("Get Data Template for Object {0}", item);

                DataTemplate _dataTemplate = null;

                IMvxViewModel viewModel = item as IMvxViewModel;
                Type viewType;

                if (item != null)
                {

                    if (Cache.ContainsKey(viewModel))
                    {

                        Console.WriteLine("Tab in cache, returning cached data.");
                        _dataTemplate = Cache[viewModel];

                    }
                    else
                    {

                        viewType = ViewsContainer.GetViewType(viewModel.GetType());

                        Console.WriteLine("View Type {0}, ViewModel {1}", viewType, viewModel);

                        _dataTemplate = new DataTemplate(() =>
                        {

                            IMvxView view = (IMvxView)Activator.CreateInstance(viewType);
                            view.DataContext = viewModel;
                            Page page = (Page)view;

                            MvxNavigationPage navigationPage = new MvxNavigationPage(page);
                            navigationPage.Title = page.Title;
                            navigationPage.Icon = page.Icon;

                            return navigationPage;

                        });
                        // Cache DataTemplate
                        Cache[viewModel] = _dataTemplate;
                    }
                }
                return _dataTemplate;
                }
        }
       // ... End of HomeViewModel class

Любая помощь или указатели приветствуются!

Другие примечания:

  • Страница с вкладками имеет следующие атрибуты: [MvxTabbedPagePresentation(TabbedPosition.Root, NoHistory = true, WrapInNavigationPage = false)]

  • Свойство ItemSource является списком MvxViewModel объектов.

  • Свойство ItemTemplate является DataTemplate, которое создает соответствующий Pageи упаковывает его в NavigationPage.

  • MvvmCross 6.2.2, Xamarin Forms 3.4

...