2017/9/14

Xamarin.Forms 教學系列文(二十五.壹)Master Detail Page




學習目標
  • MasterDetailPage 左上角海苔條

建構 Xamarin.Forms App 時,可以想像你在蓋一棟大樓,

Visual Element 是大樓內的元件,
Layout 則是一面牆壁或是畫布,可以隨意放置任何的 Visual Element,

而 Page 就是房間,能容納各種 Layout,

上一章節學會的 Navigation,就是將每個房間鏈結起來的通道。

一路學來其實已經看過兩種 Page,一為常見的 ContentPage,二為上一章節的 NavigationPage

本章要來介紹兩個新的 Page,MasterDetailPage TabbedPage

先來看 MasterDetailPage

MasterDetailPage

MasterDetailPage 定義了兩個屬性,Master Detail

分別能放入不同種類的 Page,例如在 Master 放 ContentPage,而 Detail 放 NavigationPage

簡單來說,Master 就是按下海苔條滑出來的那一塊,而 Detail 就是原本的主畫面

常用的 Google Map 就是一個 MasterDetailPage

Detail
Master



Master 又細分成兩種顯示方式,Split Popover

上面看到的範例是 Popover

Split 是在畫面中同時出現 Master 和 Detail,通常在 平板上才會看到,例如:

平板的空間比較足夠,才能這樣顯示。

而這樣的顯示行為由一個 MasterBehavior 屬性來控制,有五個值可指派:
  • Default
  • Split
  • SplitOnLandscape
  • SplitOnPortrait
  • Popover
這五個設定值,有關 Split 的在一般手機上都無作用

我們直接來看範例,了解 MasterDetail 如何使用:

這邊我們改造 19 章 的學生範例,當點選一個 ListView 的項目時,顯示此項目的詳細資料,

將 ListView 移至 Master 內,點選後由 Detail 顯示詳細資料:
*OnPlatform 寫法已更改,請參考此篇文章


<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
                  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                  xmlns:school="clr-namespace:SchoolOfFineArt;assembly=SchoolOfFineArt"
                  x:Class="SchoolAndDetail.SchoolAndDetailPage"
                  IsPresented="True">
    <!--IsPresented 這屬性在控制 Master 是否顯示-->

    <!--Master Page-->
    <MasterDetailPage.Master>
        <ContentPage Title="School">
            <ContentPage.Padding>
                <OnPlatform x:TypeArguments="Thickness"
                            iOS="0, 20, 0, 0" />
            </ContentPage.Padding>
            
            <!--BindingContext-->
            <ContentPage.BindingContext>
                <school:SchoolViewModel />
            </ContentPage.BindingContext>
            
            <StackLayout BindingContext="{Binding StudentBody}">
                <Label Text="{Binding School}"
                       FontSize="Large"
                       FontAttributes="Bold"
                       HorizontalTextAlignment="Center" />
                
                <!--ListView,顯示所有學生資料-->
                <ListView x:Name="listView"
                          ItemsSource="{Binding Students}"
                          ItemTapped="OnListViewItemTapped">
                    <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>
    </MasterDetailPage.Master>
    
    <!-- Detail Page,顯示單筆學生資料 -->
    <MasterDetailPage.Detail>
        
        <!--Detail 內放 NavigationPage-->
        <NavigationPage>
            <x:Arguments>
                <!--ContentPage 綁定 listView 點選的項目-->
                <ContentPage Title="{Binding FirstName}"
                             BindingContext="{Binding Source={x:Reference listView},
                                                      Path=SelectedItem}">
                    
                    <StackLayout>
                        <!-- Name -->
                        <StackLayout Orientation="Horizontal"
                                     HorizontalOptions="Center"
                                     Spacing="0">
                            <Label Text="{Binding LastName}" />
                            <Label Text="{Binding FirstName, StringFormat=', {0}'}" />
                            <Label Text="{Binding MiddleName, StringFormat=' {0}'}" />
                        </StackLayout>
                        
                        <!-- Photo -->
                        <Image Source="{Binding PhotoFilename}"
                               VerticalOptions="FillAndExpand" />
                        <!-- Sex -->
                        <Label Text="{Binding Sex, StringFormat='Sex = {0}'}"
                               HorizontalOptions="Center" />
                        <!-- GPA -->
                        <Label Text="{Binding GradePointAverage, StringFormat='G.P.A. = {0:F2}'}"
                               HorizontalOptions="Center" />
                    </StackLayout>
                </ContentPage>
            </x:Arguments>
        </NavigationPage>
    </MasterDetailPage.Detail>
</MasterDetailPage>

這邊除了了解 Master 和 Detail 的寫法外,要注意的是開頭的 IsPresented 屬性,拿來控制 Master 是否顯示。


最後在 .cs 內做一點小事,若 listView 點擊後就將 Master 縮起來:
    public partial class SchoolAndDetailPage : MasterDetailPage
    {
        public SchoolAndDetailPage()
        {
            InitializeComponent();
        }
        void OnListViewItemTapped(object sender, ItemTappedEventArgs args)
        {
            // Show the detail page.
            IsPresented = false;
        }
    }
注意,隱藏 Master 這件事寫在 ItemTapped 而不是 ItemSelected,意思就是當使用者點選同一筆資料時,Master 還是會隱藏起來!

點擊後:


那如果在平板上執行就會變成這樣~ Split 的顯示方式:


這範例相對單純的將 Master 和 Detail 放在同一個 XAML 底下,並用 BindingContext 做資料鏈結,

但實際運用時,常常會在 Master 點擊後的 .cs,去控制 Detail 要導向或顯示的頁面呢!



沒有留言:

張貼留言