標籤式頁面
這裡將會提供兩種標籤頁面的實作說明,一個是透過了
TabbedPage.ItemTemplate
來自訂每個子標籤頁面要出現的內容,透過了資料繫結與 Converter 轉換器的實作,讓每個子標籤頁面顯示不同的內容;透過這樣的設計,每個子標籤頁面的內容與控制項都是一樣的,只不過可以顯示出多筆資料到不同的標籤頁面上。
另外一種標籤頁面的專案實作說明,將會著重在每個子標籤頁面的明細部分,都會有屬於自己專屬的 XAML 控制項,所以,每個子標籤頁面就會長的不一樣,甚至可以做更多豐富的控制與顯示效果。
在這個範例中,將會繼續使用 Font Awesome 功能,若不知道如何設定與使用 Font Awesome,請參考 使用者登入。
建立標籤式的樣板式頁面方案
- 首先,開啟您的 Visual Studio 2015
- 接著透過 Visual Studio 2015 功能表,選擇這些項目
檔案
>新增
>專案
準備新增一個專案。 - 接著,Visual Studio 2015 會顯示
新增專案
對話窗,請在這個對話窗上,進行選擇Visual C#
>Cross-Platform
>Blank Xaml App (Xamarin.Forms Portable)
- 接著,在最下方的
名稱
文字輸入盒處,輸入TabPage1
這個名稱,最後使用滑鼠右擊右下方的確定
按鈕。 - 當專案建立到一半,若您的開發環境還沒有建置與設定完成 Mac 電腦與 Xamarin Studio for Mac 系統,此時會看到
Xamarin Mac Agent Instructions
對話窗出現,這個對話窗是要提醒您進行與 Mac 電腦連線設定,這是因為,您無法在 Windows 作業系統進行 iOS 相關應用程式的建立與設計工作,而是需要透過 Mac 電腦安裝的 XCode 來協助您完成這些 iOS 應用程式的建立工作。不過,這不影響您繼續開發 Xamarin.Forms 的應用程式,只不過此時,您無法編譯與執行 iOS 的應用程式。 - 接著會看到
新的通用Windows專案
對話視窗,此時,您只需要按下確定
按鈕即可,此時,專案精靈會繼續完成相關平台的專案建立工作。 - 最後,整個新的 Xamarin.Forms 專案就建立完成了。
開始開發 籤式的樣板式頁面
請參考底下說明,依序實作相關指示內容,以便完成該專案實作。
建立 籤式的樣板式頁面 主畫面 (MainPage.xaml)
打開 核心PCL 專案內的
MainPage.xaml
檔案,依據底下 XAML 宣告,置換所有 XAML 宣告內容。
新建立的 MainPage.xaml 的宣告定義中,可以看到該頁面的根視覺控制項已經從
ContentPage
變換成為TabbedPage
,這表示這個頁面將會是一個標籤式頁面。
在這個
TabPage1.MainPage
標籤事頁面定義內容中,有兩個節點:- TabbedPage.Resources在這裡,將會宣告定義這個標籤式頁面需要用到的 XAML 資源 (Resource),在這裡,定義了一個名為
booleanConverter
的轉換器資源 (Converter Resource),在後面的 XAML 定義中,將會透過資料繫結與這個轉換器,依據當時綁定的資料,決定那些版面配置與視覺控制項是否要顯示出來;因此,透過這樣的技巧,可以讓不同的標籤子頁面,顯示出不同的內容與效果。 - TabbedPage.ItemTemplate這個節點,將會用來定義每個子標籤頁面要顯示那些視覺控制項。每個子標籤頁面會垂直依序顯示出名稱、圖片、家族、該圖片的明細介紹(這部分會依據當時資料的定義,顯示不同的 StackLayout 版面配置、Genus值。在
DataTemplate
節點中,可以看到,每個標籤頁面,都是使用ContentPage
這個物件,在ContentPage
物件內,有許多StackLayout
版面配置控制項,用來顯示出更多明細資訊。
MainPage.xaml 的宣告定義內容
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TabPage1"
x:Class="TabPage1.MainPage"
Title="標籤頁面"
>
<TabbedPage.Resources>
<ResourceDictionary>
<local:NonNullToBooleanConverter x:Key="booleanConverter" />
</ResourceDictionary>
</TabbedPage.Resources>
<TabbedPage.ItemTemplate>
<DataTemplate>
<ContentPage Title="{Binding Name}"
BackgroundColor="{Binding Color}"
>
<StackLayout Padding="5, 25">
<Label Text="{Binding Name}"
Font="Bold,Large"
HorizontalOptions="Center" />
<Image Source="{Binding PhotoUrl}"
WidthRequest="200"
HeightRequest="200" />
<StackLayout Padding="50, 10">
<StackLayout Orientation="Horizontal">
<Label Text="Family:"
HorizontalOptions="FillAndExpand" />
<Label Text="{Binding Family}"
Font="Bold,Medium" />
</StackLayout>
<StackLayout Orientation="Horizontal"
IsVisible="{Binding Subfamily,
Converter={StaticResource booleanConverter}}">
<Label Text="Subfamily:"
HorizontalOptions="FillAndExpand" />
<Label Text="{Binding Subfamily}"
Font="Bold,Medium" />
</StackLayout>
<StackLayout Orientation="Horizontal"
IsVisible="{Binding Tribe,
Converter={StaticResource booleanConverter}}">
<Label Text="Tribe:"
HorizontalOptions="FillAndExpand" />
<Label Text="{Binding Tribe}"
Font="Bold,Medium" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Genus:"
HorizontalOptions="FillAndExpand" />
<Label Text="{Binding Genus}"
Font="Bold,Medium" />
</StackLayout>
</StackLayout>
</StackLayout>
</ContentPage>
</DataTemplate>
</TabbedPage.ItemTemplate>
</TabbedPage>
接著來修改這個 MainPage.xaml 的 code-behind 的 C# 程式碼,打開
MainPage.xaml.cs
檔案,依照底下列出程式碼,進行修正。
在這裡,您僅僅需要在建構式中,將
MonkeyDataModel.All
的值,指定給 TabbedPage
這個控制項的屬性ItemSource
,這樣,這個標籤頁面控制項,就會知道要顯示那些資料了。
其中,
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
這個在 namespace 關鍵字前的宣告,在開發 Xamarin.Forms 上是相當重要的,因為,當您加入了底下這行宣告,則該 .xaml 檔案內的 XAML 內容,就會在編譯時期進行檢查;當有錯誤的語法或者內容在編譯時期發現到之後,就不會讓這個應用程式繼續執行,直到您將這些有錯誤的 XAML 內修正完成後,才能夠正確執行。反過來說,預設 XAML 語法或者內容有錯誤的時候,往往必須要到執行時期,並且開啟這個頁面的時候,應用程式才會顯示例外異常訊息,這將會造成您的應用程式閃退。
最後,請記得要將
MainPage
這個類別,要繼承這個類別 TabbedPage
。MainPage.xaml.cs 的 code-behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace TabPage1
{
public partial class MainPage : TabbedPage
{
public MainPage()
{
InitializeComponent();
ItemsSource = MonkeyDataModel.All;
}
}
}
建立 MonkeyDataModel 資料模型
請在 核心PCL 專案節點上,使用滑鼠右擊該節點,在彈出功能表中,點選
加入
> 類別
,在 加入新項目 TabPage1
對話窗內,選擇 Visual C#
> 類別
,接著在底下 名稱
欄位中,輸入 MonkeyDataModel.cs
,以便建立一個新的類別檔案。
在這個類別中,定義了六個屬性,與一個靜態
IList
的屬性 All;接著,在靜態建構式內,進行 All 這個屬性的初始化,這個 All 的屬性值內容,將會出現在每個標籤頁面內。
在每個頁面物件中,
Color
這個屬性,表示該標籤頁面的背景顏色,這個值會透過資料繫結 (Data Binding)的方式,綁定到 XAML 的背景顏色屬性內。MonkeyDataModel.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace TabPage1
{
public class MonkeyDataModel
{
public string Name { set; get; }
public string Family { set; get; }
public string Subfamily { set; get; }
public string Tribe { set; get; }
public string Genus { set; get; }
public string PhotoUrl { set; get; }
public Color Color { set; get; }
public static IList<MonkeyDataModel> All { set; get; }
static MonkeyDataModel()
{
All = new ObservableCollection<MonkeyDataModel> {
new MonkeyDataModel {
Name = "Chimpanzee",
Family = "Hominidae",
Subfamily = "Homininae",
Tribe = "Panini",
Genus = "Pan",
PhotoUrl = "http://upload.wikimedia.org/wikipedia/commons/thumb/6/62/Schimpanse_Zoo_Leipzig.jpg/640px-Schimpanse_Zoo_Leipzig.jpg",
Color = Color.Green
},
new MonkeyDataModel {
Name = "Orangutan",
Family = "Hominidae",
Subfamily = "Ponginae",
Genus = "Pongo",
PhotoUrl = "http://upload.wikimedia.org/wikipedia/commons/b/be/Orang_Utan%2C_Semenggok_Forest_Reserve%2C_Sarawak%2C_Borneo%2C_Malaysia.JPG",
Color = Color.Yellow
},
new MonkeyDataModel {
Name = "Tamarin",
Family = "Callitrichidae",
Genus = "Saguinus",
PhotoUrl = "http://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Tamarin_portrait_2_edit3.jpg/640px-Tamarin_portrait_2_edit3.jpg",
Color = Color.Pink
}
};
}
}
}
建立 NonNullToBooleanConverter 轉換器
請在 核心PCL 專案節點上,使用滑鼠右擊該節點,在彈出功能表中,點選
加入
> 類別
,在 加入新項目 TabPage1
對話窗內,選擇 Visual C#
> 類別
,接著在底下 名稱
欄位中,輸入NonNullToBooleanConverter.cs
,以便建立一個新的類別檔案。 將底下的 C# 程式碼,這換掉NonNullToBooleanConverter.cs
的內容。
在底下的 C# 程式碼,是一個非常典型的 XAML 轉換器的應用做法;當您需要在 XAML 裡面,想將一個物件,轉換成為另外一種物件,就可以使用轉換器這樣的作法。
首先,產生一個類別,該類別需要實作出
IValueConverter
這個介面,該介面裡面有兩個方法 Convert
,ConvertBack
,通常來說,大部分的程式設計師僅會用到前者,因此,在這裡也是一樣。在 Convert
這個方法中,會接收到 XAML 傳送過來的物件,此時,在這裡判斷該物件是否為 string
類型,若為 string
類型且字串物件有字串存在,也就是不是 null 或者空字串,該方法就會回傳 true,也就是在 XAML 中,需要顯示相對應的 StackLayout
。NonNullToBooleanConverter.cs
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace TabPage1
{
class NonNullToBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string)
{
return !string.IsNullOrEmpty((string)value);
}
return value != null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
}
建立
建立
執行結果
底下分別來查看在不同平台下,執行這個應用程式所看到的成果是甚麼?
Android 執行結果
請在方案總管內,滑鼠右擊
TabPage1.Droid
專案,選擇 設定為起始專案
,接著按下 F5
開始執行。iOS 執行結果
請在方案總管內,滑鼠右擊
TabPage1.iOS
專案,選擇 設定為起始專案
,接著按下 F5
開始執行。參考
建立標籤式的可導航頁面方案
- 首先,開啟您的 Visual Studio 2015
- 接著透過 Visual Studio 2015 功能表,選擇這些項目
檔案
>新增
>專案
準備新增一個專案。 - 接著,Visual Studio 2015 會顯示
新增專案
對話窗,請在這個對話窗上,進行選擇Visual C#
>Cross-Platform
>Blank Xaml App (Xamarin.Forms Portable)
- 接著,在最下方的
名稱
文字輸入盒處,輸入TabPage2
這個名稱,最後使用滑鼠右擊右下方的確定
按鈕。 - 當專案建立到一半,若您的開發環境還沒有建置與設定完成 Mac 電腦與 Xamarin Studio for Mac 系統,此時會看到
Xamarin Mac Agent Instructions
對話窗出現,這個對話窗是要提醒您進行與 Mac 電腦連線設定,這是因為,您無法在 Windows 作業系統進行 iOS 相關應用程式的建立與設計工作,而是需要透過 Mac 電腦安裝的 XCode 來協助您完成這些 iOS 應用程式的建立工作。不過,這不影響您繼續開發 Xamarin.Forms 的應用程式,只不過此時,您無法編譯與執行 iOS 的應用程式。 - 接著會看到
新的通用Windows專案
對話視窗,此時,您只需要按下確定
按鈕即可,此時,專案精靈會繼續完成相關平台的專案建立工作。 - 最後,整個新的 Xamarin.Forms 專案就建立完成了。
開始開發 籤式的樣板式頁面
請參考底下說明,依序實作相關指示內容,以便完成該專案實作。
建立 籤式的樣板式頁面 主畫面 (MainPage.xaml)
打開 核心PCL 專案內的
MainPage.xaml
檔案,依據底下 XAML 宣告,置換所有 XAML 宣告內容。
新建立的 MainPage.xaml 的宣告定義中,可以看到該頁面的根視覺控制項已經從
ContentPage
變換成為TabbedPage
,這表示這個頁面將會是一個標籤式頁面。
在這個
TabPage2.MainPage
標籤事頁面定義,使用 XAML 節點,定義了三個標籤子頁面,分別為:ContentPage
, NavigationPage
, ContentPage
。MainPage.xaml 的宣告定義內容
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TabPage2"
x:Class="TabPage2.MainPage">
<local:TodayPage />
<NavigationPage Title="Schedule" >
<x:Arguments>
<local:SchedulePage />
</x:Arguments>
</NavigationPage>
<local:SettingsPage />
</TabbedPage>
建立 TodayPage.xaml 頁面
使用滑鼠右擊 核心PCL 專案,從彈出功能表中,點選
加入
> 新增項目
;接著,在 加入新項目 - TabPage2
對話窗內,點選 Visual C#
> Cross-Platform
> Forms Xaml Page
,最後,在底下名稱欄位的文字輸入盒中,輸入 TodayPage
。
接著,請將下列 XAML 定義替換掉新建立的 .xaml 檔案內容。
TodayPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TabPage2.TodayPage"
Title="Today">
<ContentPage.Content>
<StackLayout>
<Label Text="Today's appointments go here" HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
建立 SchedulePage.xaml 頁面
使用滑鼠右擊 核心PCL 專案,從彈出功能表中,點選
加入
> 新增項目
;接著,在 加入新項目 - TabPage2
對話窗內,點選 Visual C#
> Cross-Platform
> Forms Xaml Page
,最後,在底下名稱欄位的文字輸入盒中,輸入 SchedulePage
。
接著,請將下列 XAML 定義替換掉新建立的 .xaml 檔案內容。
在這個頁面,只有包含
Label
文字標籤 與 Button
按鈕 兩個控制項,因為在 Button
控制項中有定義了 Clicked 事件,因此,需要在 code-behind 內定義該點擊事件該做甚麼事情。SchedulePage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TabPage2.SchedulePage"
Title="This Week">
<ContentPage.Content>
<StackLayout>
<Label
Text="This week's appointments go here"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button
Text="Upcoming Appointments"
Clicked="OnUpcomingAppointmentsButtonClicked"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
SchedulePage.xaml.cs
請打開
SchedulePage.xaml
的 code-behind 檔案 SchedulePage.xaml.cs
,並請將下列 C# 程式碼換掉現在內容。
在這個 code-behind 內,按鈕事件只有做一件事情,那就是通知導航頁面 (NavigationPage),切換到
UpcomingAppointmentsPage
新頁面。using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace TabPage2
{
public partial class SchedulePage : ContentPage
{
public SchedulePage()
{
InitializeComponent();
}
async void OnUpcomingAppointmentsButtonClicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new UpcomingAppointmentsPage());
}
}
}
建立 UpcomingAppointmentsPage.xaml 頁面
使用滑鼠右擊 核心PCL 專案,從彈出功能表中,點選
加入
> 新增項目
;接著,在 加入新項目 - TabPage2
對話窗內,點選 Visual C#
> Cross-Platform
> Forms Xaml Page
,最後,在底下名稱欄位的文字輸入盒中,輸入 UpcomingAppointmentsPage
。
接著,請將下列 XAML 定義替換掉新建立的 .xaml 檔案內容。
在這個頁面,只有包含
Label
文字標籤 與 Button
按鈕 兩個控制項,因為在 Button
控制項中有定義了 Clicked 事件,因此,需要在 code-behind 內定義該點擊事件該做甚麼事情。UpcomingAppointmentsPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TabPage2.UpcomingAppointmentsPage"
Title="Upcoming">
<ContentPage.Content>
<StackLayout>
<Label
Text="Upcoming appointments go here"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Button
Text="Back"
Clicked="OnBackButtonClicked"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
UpcomingAppointmentsPage.xaml.cs
請打開
UpcomingAppointmentsPage.xaml
的 code-behind 檔案 UpcomingAppointmentsPage.xaml.cs
,並請將下列 C# 程式碼換掉現在內容。
在這個 code-behind 內,按鈕事件只有做一件事情,那就是通知導航頁面 (NavigationPage),返回到上衣個頁面。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
namespace TabPage2
{
public partial class UpcomingAppointmentsPage : ContentPage
{
public UpcomingAppointmentsPage()
{
InitializeComponent();
}
async void OnBackButtonClicked(object sender, EventArgs e)
{
await Navigation.PopAsync();
}
}
}
建立 SettingsPage.xaml 頁面
使用滑鼠右擊 核心PCL 專案,從彈出功能表中,點選
加入
> 新增項目
;接著,在 加入新項目 - TabPage2
對話窗內,點選 Visual C#
> Cross-Platform
> Forms Xaml Page
,最後,在底下名稱欄位的文字輸入盒中,輸入 SettingsPage
。
接著,請將下列 XAML 定義替換掉新建立的 .xaml 檔案內容。
SettingsPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TabPage2.SettingsPage"
Title="Settings">
<ContentPage.Content>
<StackLayout>
<Label
Text="Settings go here"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
執行結果
底下分別來查看在不同平台下,執行這個應用程式所看到的成果是甚麼?
Android 執行結果
請在方案總管內,滑鼠右擊
TabPage2.Droid
專案,選擇 設定為起始專案
,接著按下 F5
開始執行。iOS 執行結果
請在方案總管內,滑鼠右擊
TabPage2.iOS
專案,選擇 設定為起始專案
,接著按下 F5
開始執行。
TabbedPage
標籤頁面 (另外四種分別為ContentPage
內容頁面,MasterDetailPage
導航抽屜頁面,NavigationPage
導航頁面,CarouselPage
旋轉木馬頁面,其中,前三者在前面的章節中已經出現過了,而且有展示如何使用,最後一個旋轉木馬頁面,將會於下一個章節來介紹); Xamarin.Forms 提供的TabbedPage
標籤頁面是由許多標籤與其要顯示的明細內容所組成,因此,透過標籤頁面可以讓使用者自行切換查看不同的內容,但是卻不需要做任何頁面切換的導航,並且可以自訂每個標籤頁面所要出現內容與控制項。