TabbedPage
TabbedPage派生自抽象类MultiPage 。它维护一个Page类型的子集合,其中只有一个一次完全可见。 TabbedPage通过页面顶部或底部的一系列选项卡标识每个子项。使用TabbedPage的iOS应用程序必须包含每个选项卡的图标;否则,Apple将不接受App Store的程序。此图标通过每个页面的Icon属性设置。
MultiPage 定义TabbedPage的所有重要属性和事件,其中最重要的是:
- IList类型的子属性。
通常,您使用页面对象填充此Children集合。
但是,您可以通过观察MultiPage 与ListView的基类ItemsView 非常相似来以稍微不同的方式使用TabbedPage,因为它定义了:
- IEnnumerable类型的ItemsSource属性,和
- DataTemplate类型的ItemTemplate属性。
如果提供具有适合数据绑定的公共属性的IEnumerable对象集合,以及具有页面类型作为根元素的模板,则会动态生成子项。该
每个生成的页面的BindingContext设置为等于ItemsSource中的特定对象。
MultiPage 定义了两个属性,可以帮助您的应用程序跟踪用户当前正在查看的Children集合中的哪个页面:
- T类型的CurrentPage(TabbedPage的页面)。
- 类型为object的SelectedItem,引用ItemsSource集合中的对象。两个属性都是gettable和settable。
MultiPage 还定义了两个事件:
- TartsSource集合更改时触发PagesChanged
- 查看的页面更改时会触发CurrentPageChanged。
最常见的是,您将直接将ContentPage衍生物添加到Children集合中。 如果要使用TabbedPage基于数据集合显示类似页面的集合,您可以选择将ItemsSource属性设置为该集合并使用ItemTemplate定义页面,但在iOS上应避免使用此方法。
离散标签页
TabbedPage的最常见用途是在应用程序中的不同功能之间导航,这通常意味着每个选项卡呈现不同类型的页面。 这些页面通常以某种方式相关 - 也许是应用程序设置的多个页面 - 即使它们看起来不一样。
DiscreteTabbedColors程序有三个选项卡:第一个显示内置Xamarin.Forms颜色的列表,第二个显示Xamarin.FormsBook.Toolkit(前面章节中介绍)中NamedColor类的颜色列表,第三个选项卡 包含颜色测试仪(您可以使用它选择任意RGB值进行预览)。
DiscreteTabbedColors程序以三个ContentPage衍生物开头。 第一个是codeonly,由一个简单的标准Xamarin.Forms颜色列表组成。
class BuiltInColorsPage : ContentPage
{
public BuiltInColorsPage()
{
Title = "Built-in";
Icon = Device.OnPlatform("ic_action_computer.png", null, null);
Padding = new Thickness(5, Device.OnPlatform(20, 5, 5), 5, 5);
double fontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label));
Content = new ScrollView
{
Content = new StackLayout
{
Spacing = 0,
Children =
{
new Label
{
Text = "White",
TextColor = Color.White,
FontSize = fontSize
},
__
new Label
{
Text = "Purple",
TextColor = Color.Purple,
FontSize = fontSize
}
}
}
};
}
}
请注意,Title属性已设置。 这对于所有平台上的选项卡文本都很重要。 该代码还为iOS设置了Icon属性。 特定图标是第13章“位图”中描述的Android图标集的一部分,并且是32像素的正方形。
NamedColorsPage由所有NamedColor对象的ListView组成。 再次注意iOS的Title属性和Icon属性:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit=
"clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit"
x:Class="DiscreteTabbedColors.NamedColorsPage"
Title="Toolkit">
<ContentPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource"
iOS="ic_action_storage.png" />
</ContentPage.Icon>
<ListView ItemsSource="{x:Static toolkit:NamedColor.All}">
<ListView.RowHeight>
<OnPlatform x:TypeArguments="x:Int32"
iOS="80"
Android="80"
WinPhone="90" />
</ListView.RowHeight>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView Padding="5">
<StackLayout Orientation="Horizontal">
<BoxView x:Name="boxView"
Color="{Binding Color}"
WidthRequest="50"
HeightRequest="50" />
<StackLayout>
<Label Text="{Binding Name}"
FontSize="Medium"
VerticalOptions="StartAndExpand" />
<Label Text="{Binding RgbDisplay, StringFormat='RGB = {0}'}"
FontSize="Small"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</StackLayout>
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
第三页包含三个Slider元素来选择颜色,例如您之前见过的:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:toolkit=
"clr-namespace:Xamarin.FormsBook.Toolkit;assembly=Xamarin.FormsBook.Toolkit"
x:Class="DiscreteTabbedColors.ColorTestPage"
Title="Test">
<ContentPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource"
iOS="ic_action_gamepad.png" />
</ContentPage.Icon>
<StackLayout Padding="20, 40">
<StackLayout.BindingContext>
<toolkit:ColorViewModel Color="Gray" />
</StackLayout.BindingContext>
<Label Text="{Binding Red, StringFormat='Red = {0:F2}'}"
HorizontalOptions="Center" />
<Slider Value="{Binding Red}" />
<Label Text="{Binding Green, StringFormat='Green = {0:F2}'}"
HorizontalOptions="Center" />
<Slider Value="{Binding Green}" />
<Label Text="{Binding Blue, StringFormat='Blue = {0:F2}'}"
HorizontalOptions="Center" />
<Slider Value="{Binding Blue}" />
<BoxView Color="{Binding Color}"
VerticalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
这是DiscreteTabbedColorsPage。 注意TabbedPage的根元素。 此XAML文件只是将这三种页面类型的实例添加到TabbedPage的Children集合中:
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:local="clr-namespace:DiscreteTabbedColors"
x:Class="DiscreteTabbedColors.DiscreteTabbedColorsPage">
<local:BuiltInColorsPage />
<local:NamedColorsPage />
<local:ColorTestPage />
</TabbedPage>
以下是三个平台上的三个选项卡:
在iOS上,选项卡位于底部,标有文本和图标,突出显示所选选项卡。 Android和Windows 10 Mobile都会在屏幕顶部显示选项卡,但会以不同方式突出显示所选选项卡。
StudentNotes程序有一个主页,列出ListView中的所有学生,但从该列表中选择一个学生会导致程序导航到TabbedPage。该页面有三个选项卡:第一个显示关于学生的文本信息,第二个显示学生的照片,第三个显示编辑器,允许教师或其他学校管理员输入关于学生的一些注释。 (此功能使用SchoolOfFineArt库中Student类的Notes属性。)
StudentNotes程序中的App类将Application定义的Properties字典传递给SchoolViewModel构造函数,并在程序进入休眠状态时将Properties字典传递给ViewModel的SaveNotes方法,可能是为了准备终止:
public class App : Application
{
public App()
{
ViewModel = new SchoolViewModel(Properties);
MainPage = new NavigationPage(new StudentNotesHomePage());
}
public SchoolViewModel ViewModel
{
private set; get;
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
ViewModel.SaveNotes(Properties);
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
现在主页应该看起来很熟悉。 它只显示ListView中的所有学生:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:StudentNotes;assembly=StudentNotes"
x:Class="StudentNotes.StudentNotesHomePage"
Title="Students"
BindingContext="{Binding Source={x:Static Application.Current},
Path=ViewModel}">
<StackLayout BindingContext="{Binding StudentBody}">
<Label Text="{Binding School}"
FontSize="Large"
FontAttributes="Bold"
HorizontalTextAlignment="Center" />
<ListView x:Name="listView"
ItemsSource="{Binding Students}"
ItemSelected="OnListViewItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell ImageSource="{Binding PhotoFilename}"
Text="{Binding FullName}"
Detail="{Binding GradePointAverage,
StringFormat='G.P.A. = {0:F2}'}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
代码隐藏文件包含ListView的ItemSelected处理程序,用于导航到StudentNotesDataPage,将页面的BindingContext设置为选定的Student对象:
public partial class StudentNotesHomePage : ContentPage
{
public StudentNotesHomePage()
{
InitializeComponent();
}
async void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs args)
{
if (args.SelectedItem != null)
{
listView.SelectedItem = null;
await Navigation.PushAsync(new StudentNotesDataPage
{
BindingContext = args.SelectedItem
});
}
}
}
StudentNotesDataPage派生自TabbedPage。 在TabbedPage的开始和结束标记内,三个ContentPage定义被添加到TabbedPage的Children属性中。 每个都将其Title属性设置为要在选项卡中使用的文本,并为iOS包含Icon定义:
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="StudentNotes.StudentNotesDataPage"
Title="Student Data">
<ContentPage Title="Info">
<ContentPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource"
iOS="ic_action_about.png" />
</ContentPage.Icon>
<StackLayout>
<Label Text="{Binding FullName}"
FontSize="Large"
HorizontalOptions="Center" />
<StackLayout Spacing="12"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center">
<StackLayout.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="Large" />
</Style>
</ResourceDictionary>
</StackLayout.Resources>
<Label Text="{Binding LastName,
StringFormat='Last name: {0}'}" />
<Label Text="{Binding FirstName,
StringFormat='First name: {0}'}" />
<Label Text="{Binding MiddleName,
StringFormat='Middle name: {0}'}" />
<Label Text="{Binding Sex,
StringFormat='Sex: {0}'}" />
<Label Text="{Binding GradePointAverage,
StringFormat='G.P.A. = {0:F2}'}" />
</StackLayout>
</StackLayout>
</ContentPage>
<ContentPage Title="Photo">
<ContentPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource"
iOS="ic_action_person.png" />
</ContentPage.Icon>
<StackLayout>
<Label Text="{Binding FullName}"
FontSize="Large"
HorizontalOptions="Center" />
<Image Source="{Binding PhotoFilename}"
VerticalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
<ContentPage Title="Notes">
<ContentPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource"
iOS="ic_action_edit.png" />
</ContentPage.Icon>
<StackLayout>
<Label Text="{Binding FullName}"
FontSize="Large"
HorizontalOptions="Center" />
<Editor Text="{Binding Notes}"
Keyboard="Text"
VerticalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
</TabbedPage>
这可能不足以分散三页,但您可以轻松想象这种方法理想的情况。
以下是三个平台在三个平台上的外观:
您可以按正常方式导航回学生列表:点击iOS和Android屏幕顶部的左箭头,或者按Android和Windows 10 Mobile屏幕底部的后退箭头。