XAML in Xamarin.Forms 基礎篇 電子書

XAML in Xamarin.Forms 基礎篇 電子書
XAML in Xamarin.Forms 基礎篇 電子書

Xamarin.Forms 快速入門 電子書

Xamarin.Forms 快速入門 電子書
Xamarin.Forms 快速入門 電子書

2018/05/23

Xamarn.Forms TabbedPage 標籤式頁面的不同情境之使用

在從事 Xamarin.Forms 教學經驗中,有許多人都在詢問要如何設計出具有 TabbedPage 標籤式頁面 功能,不過,因為我個人比較少使用這個頁面,通常遇到這樣的視覺需求,我都是自行設計使用者控制向來完成這樣的需求,因此,在這篇文章中,我們將要來體驗 TabbedPage 標籤式頁面在 Xamarin.Forms 中要如何使用?不過,我們在這裡所練習的架構,是採用 Prism 框架下的 MVVM 設計模式,並且需要使用到 Prism7 的版本才能夠時做出來。
這篇文章所提到的所有專案原始碼,可以從 這裡 取得
在我們的練習情境之中,我們需要設計一個應用程式的首頁為 TabbedPage 標籤式頁面,在這個 TabbedPage 標籤式頁面中,共會存在四個標籤 (在 Prism7 中,我們可以使用這個查詢字串 createTab 來完成宣告,這個標籤頁面總共需要有多少個頁面存在),不過,我們需要指定第三個標籤頁面為我們預設顯示的頁面,底下為我們實際執行後的螢幕截圖,預設顯示第三頁面內容 (在 Prism7 中,我們可以使用這個查詢字串 selectedTab 來指定預設顯示的頁次是哪個)。
TabbedPage 標籤式頁面
另外,我們希望切換到第二個標籤頁面的時候,他是具有導航工具列的效果,也就是說,我們切換到第二頁的時候,在第二頁內會有一個按鈕,按下這個按鈕之後,將會導航到另外一個新的頁面,在此同時,螢幕上會有導航工具列出現,如同下圖:
TabbedPage 標籤式頁面 TabbedPage 標籤式頁面
不過,若我們沒有使用 Prism7 所提供的標籤頁面之特定查詢字串,此時,我們將會變成這樣的情境,這樣的結果將不是我們所期望需要的。
TabbedPage 標籤式頁面 TabbedPage 標籤式頁面
接下來,我們來實際練習開發出這樣的應用。

建立練習專案

  • 首先,我們使用 Prism Template Pack (現在使用的 2.0.9 版本)建立起一個 Xamarin.Forms 開發專案
  • 我們需要建立一個 TabbedPage 頁面,我們把它命名為 MainTabbedPage,在這個頁面 View 與頁面檢視 ViewModel 中,我們不需要做任何特別處理。
  • 另外,因為我們需要有許多標籤頁次需要顯示,因此,我們需要建立出五個 ContentPage,所以,我們產生出五個 ContentPage,分別名稱為 Page1, Page2, Page3, Page4, Page21。 Visual Studio 2017 Solution Explorer
  • 接下來,我們需要分別將這五個 ContentPage 的 View 和 ViewModel 進行設計
  • 最後,我們需要修正 Xamarin.Forms 專案的進入點 ( Entry Point ),也就是 App.xaml.cs 檔案,我們將其打開,在 OnInitialized 方法內,將 await NavigationService.NavigateAsync 方法內需要的引數,修改成為 MainTabbedPage?createTab=Page1&createTab=NavigationPage|Page2&createTab=Page3&createTab=Page4&selectedTab=Page3
    在這裡,我們透過了查詢字串中 createTab 這個參數,指定這個標籤式頁面需要那些 ContentPage,由於我們在這個練習中,總共需要用到四個標籤頁面,所以,我們在查詢字串中,總共需要使用到四次的 createTab 。其中,您將會看到在第二個 createTab 中,其設定值似乎與其他的不太一樣,在這裡,我們需要在頁面2中,提供導航到其他頁面的機制,因此,我們需要在 createTab 參數名稱之後,先使用 NavigationPage 緊接著使用管道 | 字元,最後再加上 Page2,這表示了,第二個標籤頁面中,將會顯示出具有導航工具列的效果。
    TabbedPage 標籤式頁面
    而在頁面2中,我們放置了一個按鈕,當您按下這個按鈕之後,將會導航到 Page21 這個頁面,底下是我們所期望呈現的結果。我們可以看到,最上方會出現導航工具列,並且會有回上頁的按鈕出現,不過,新的頁面還是出現在 TabbedPage 標籤式頁面的第二個頁次中。
    TabbedPage 標籤式頁面
    若您的專案需要不想要做到這樣的結果,您可以參考頁面1的設計,在這個頁面中,我們放置了一個按鈕,按下這個按鈕,就一樣會導航到 Page21,不過,當您切換到 頁面1 頁次的時候,看到的是如下螢幕截圖,他與頁面2 的內容完全不一樣,您知道為什麼會有這樣的結果嗎?
    TabbedPage 標籤式頁面
    當我們在頁面1點選了這個按鈕,此時,將會出現如下圖內容。
    TabbedPage 標籤式頁面

MainTabbedPage 的 View 內容

<?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:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
            prism:ViewModelLocator.AutowireViewModel="True"
            x:Class="XFTabbed2.Views.MainTabbedPage">

</TabbedPage>

Page1 的 View 內容

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFTabbed2.Views.Page1"
             Title="{Binding Title}"
             BackgroundColor="LightBlue">

    <StackLayout
        >
        <Button
            Text="Go Page21"
            Command="{Binding GoNextCommand}"/>
    </StackLayout>
</ContentPage>

Page1ViewModel 的 ViewModel 程式碼

using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;

namespace XFTabbed2.ViewModels
{
    using System.ComponentModel;
    using Prism.Events;
    using Prism.Navigation;
    using Prism.Services;
    public class Page1ViewModel : INotifyPropertyChanged, INavigationAware
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string Title { get; set; }
        private readonly INavigationService _navigationService;
        public DelegateCommand GoNextCommand { get; set; }
        public Page1ViewModel(INavigationService navigationService)
        {
            _navigationService = navigationService;
            Title = "頁面 1";
            GoNextCommand = new DelegateCommand(() =>
            {
                _navigationService.NavigateAsync("Page21");
            });
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {

        }

        public void OnNavigatingTo(NavigationParameters parameters)
        {

        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {

        }

    }
}

Page2 的 View 內容

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFTabbed2.Views.Page2"
             Title="{Binding Title}"
             BackgroundColor="LightGoldenrodYellow">

    <StackLayout
        >
        <Button
            Text="Go Page21"
            Command="{Binding GoNextCommand}"/>
    </StackLayout>

</ContentPage>

Page2ViewModel 的 ViewModel 程式碼

using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;

namespace XFTabbed2.ViewModels
{
    using System.ComponentModel;
    using Prism.Events;
    using Prism.Navigation;
    using Prism.Services;
    public class Page2ViewModel : INotifyPropertyChanged, INavigationAware
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string Title { get; set; }
        private readonly INavigationService _navigationService;
        public DelegateCommand GoNextCommand { get; set; }
        public Page2ViewModel(INavigationService navigationService)
        {
            _navigationService = navigationService;
            Title = "頁面 2";
            GoNextCommand = new DelegateCommand(() =>
            {
                _navigationService.NavigateAsync("Page21");
            });
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {

        }

        public void OnNavigatingTo(NavigationParameters parameters)
        {

        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {

        }

    }
}

Page21 的 View 內容

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFTabbed2.Views.Page21"
             Title="{Binding Title}"
             BackgroundColor="LightPink">

</ContentPage>

Page21ViewModel 的 ViewModel 程式碼

using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;

namespace XFTabbed2.ViewModels
{
    using System.ComponentModel;
    using Prism.Events;
    using Prism.Navigation;
    using Prism.Services;
    public class Page21ViewModel : INotifyPropertyChanged, INavigationAware
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string Title { get; set; }
        private readonly INavigationService _navigationService;

        public Page21ViewModel(INavigationService navigationService)
        {
            _navigationService = navigationService;
            Title = "頁面 21";
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {

        }

        public void OnNavigatingTo(NavigationParameters parameters)
        {

        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {

        }

    }
}

Page3 的 View 內容

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFTabbed2.Views.Page3"
             Title="{Binding Title}"
             BackgroundColor="LightSalmon">

</ContentPage>

Page3ViewModel 的 ViewModel 程式碼

using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;

namespace XFTabbed2.ViewModels
{
    using System.ComponentModel;
    using Prism.Events;
    using Prism.Navigation;
    using Prism.Services;
    public class Page3ViewModel : INotifyPropertyChanged, INavigationAware
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string Title { get; set; }
        private readonly INavigationService _navigationService;

        public Page3ViewModel(INavigationService navigationService)
        {
            _navigationService = navigationService;
            Title = "頁面 3";
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {

        }

        public void OnNavigatingTo(NavigationParameters parameters)
        {

        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {

        }

    }
}

Page4 的 View 內容

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="XFTabbed2.Views.Page4"
             Title="{Binding Title}"
             BackgroundColor="LightSteelBlue">

</ContentPage>

Page4ViewModel 的 ViewModel 程式碼

using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;

namespace XFTabbed2.ViewModels
{
    using System.ComponentModel;
    using Prism.Events;
    using Prism.Navigation;
    using Prism.Services;
    public class Page4ViewModel : INotifyPropertyChanged, INavigationAware
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string Title { get; set; }
        private readonly INavigationService _navigationService;

        public Page4ViewModel(INavigationService navigationService)
        {
            _navigationService = navigationService;
            Title = "頁面 4";
        }

        public void OnNavigatedFrom(NavigationParameters parameters)
        {

        }

        public void OnNavigatingTo(NavigationParameters parameters)
        {

        }

        public void OnNavigatedTo(NavigationParameters parameters)
        {

        }

    }
}



沒有留言:

張貼留言