我正在使用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)
为了进行调试,我在MvxTabbedPage上的CurrentPageChanged
事件上附加了一个处理程序,并且可以确认CurrentPage
的更新正确。我还尝试了TabbedPage的设置WrapInNavigationPage = true
,但这会导致不良的导航行为。
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
属性是一个数据模板,它实例化相应的Page
并将其包装在NavigationPage
中。
MvvmCross 6.2.2,Xamarin形式3.4