XAML in Xamarin.Forms 基礎篇 電子書

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

Xamarin.Forms 快速入門 電子書

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

2016/08/17

Xamarin.Forms 使用者控制項

Xamarin.Forms 使用者控制項

在進行以 XAML 為基礎的應用程式開發過程中,使用者控制項(User Control)的使用,可以提升整個應用程式的開發速度與品質;透過建立一個使用者控制項之後,您就可以在不同的頁面中,直接引用這個新建立起來的使用者控制項,如同使用樂高積木一樣。
這份筆記的範例專案可以底下網址取得

建立使用者控制項

  1. 滑鼠右擊核心PCL專案節點,選擇 加入 > 新增項目 > Visual C# > Cross-Platform > Forms Xaml Page,並且在下方名稱欄位中,輸入這個使用者控制項的名稱,在這個範例專案中,將輸入名稱MyControl
  2. 在新產生的 .xaml 檔案中,預設產生為一個頁面,此時,需要修正 .xaml & .xaml.cs 檔案,使其成為一個使用者控制項。

MyControl.xaml

  1. 在底下 XAML 標記宣告中,根節點 (Root Element) 採用的是 Grid 版面配置項目 (Layout Element),並且在這個 Grid 版面配置項目,修正其 Margin 與 BackgroundColor 的屬性值。
  2. 接著定義了這個 Grid 版面配置,共有兩個縱列 (Column),第一個 Column 的寬度為80dp,而第二個的寬度則為剩下的可用空間。
  3. 定義一個 Label 控制項,指定在第一個 Column 版面中
  4. 定義一個 Entry 控制項,指定在第二個 Column 版面中
  5. 經過這樣的定義,您可以在這個應用程式之任何 XAML 頁面內,隨時都可以使用這個使用者控制項。
<?xml version="1.0" encoding="utf-8" ?>
<Grid 
  xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  x:Class="XFUserControl.MyControl"
  Margin="20,0,20,10"
  BackgroundColor="Lime"
  >

  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="80" />
    <ColumnDefinition Width="*"/>
  </Grid.ColumnDefinitions>
  <Label 
    Text="欄位名稱" 
    Grid.Row="0" Grid.Column="0"
    FontSize="20" TextColor="Blue"
    LineBreakMode="TailTruncation"
    VerticalOptions="Center" HorizontalOptions="Start" />
  <Entry 
    Placeholder="請輸入您的電話號碼"
    Grid.Row="0" Grid.Column="1"
    Keyboard="Telephone"
    VerticalOptions="Center" HorizontalOptions="Fill"
    />
</Grid>

MyControl.xaml.cs

  1. 由於這個使用者控制項的根節點已經定義為 Grid,所以,在 MyControl 這個類別定義中,需要從Grid 類別來繼承
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;

namespace XFUserControl
{
    public partial class MyControl : Grid
    {
        public MyControl()
        {
            InitializeComponent();
        }
    }
}

使用使用者控制項

現在回到這個專案的首頁,MainPage.xaml,並且開始使用剛剛產生的使用者控制項。

MainPage.xaml

  1. 為了要引用這個使用者控制項,需要加入一個命名空間 (namespace);在這裡定義一個mlns:local="clr-namespace:XFUserControl" 命名空間可以參考到這個使用者控制項
  2. 在這個頁面中,使用 <local:MyControl /> XAML 標記,就可以使用這個使用者控制項
  3. 執行結果如下圖
<?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:local="clr-namespace:XFUserControl"
             x:Class="XFUserControl.MainPage">

  <StackLayout
    Orientation="Vertical"
    Spacing="0"
    Padding="0,40,0,0"
    >
    <local:MyControl />
    <local:MyControl />
    <local:MyControl />
    <local:MyControl />
  </StackLayout>
</ContentPage>
使用者控制項

2016/08/16

Xamarin.Forms 的應用程式生命週期

Xamarin.Forms 的應用程式生命週期

這份筆記內容將會說明 Xamarin.Forms 的應用程式生命週期意義與用法;所謂應用程式的生命週期 (Application Life Cycle),指的是當應用程式產生、隱藏到背景或者回到前景的各種不同狀態。
在 Xamarin.Forms 的 Application 類別內,定義了三個事件,分別對應到上述的三種狀態,您可以根據這些狀態,在您的應用程式內,進行不同對應處理。
底下為 Application 類別這三個事件的宣告
  • OnStart
    表示當應用程式一旦啟動之後,就會執行這個方法。
  • OnSleep
    表示當應用程式進入到背景狀態下,例如,使用者按下了 Home 按鈕,此時您的手機回到了首頁,又或者此時您執行了別的應用程式,這些情況下,您的應用程式就會進入到背景模式下,此時,這個方法就會被執行。
  • OnResume
    表示當應用程式從背景模式下回到前景模式,也就是,使用者可以在螢幕上繼續操作與看到您的應用程式,此時,這個方法就會被執行。
        //
        // 摘要:
        //     Application developers override this method to perform actions when the application
        //     resumes from a sleeping state.
        //
        // 備註:
        //     To be added.
        protected virtual void OnResume();
        //
        // 摘要:
        //     Application developers override this method to perform actions when the application
        //     enters the sleeping state.
        //
        // 備註:
        //     To be added.
        protected virtual void OnSleep();
        //
        // 摘要:
        //     Application developers override this method to perform actions when the application
        //     starts.
        //
        // 備註:
        //     To be added.
        protected virtual void OnStart();
您可以參考底下程式碼,此時,當您的應用程式一執行後,就會在 Visual Studio 除錯視窗內看到 OnStart訊息,當您啟動別的應用程式或者按下手機上的 Home 按鈕,則Visual Studio 除錯視窗內看到 OnSleep;若您操作讓您的應用程式回到了前景模式,則您會在Visual Studio 除錯視窗內看到 OnResume 文字。
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            MainPage = new XFLifeCycle.MainPage();
        }

        protected override void OnStart()
        {
            // Handle when your app starts
            Debug.WriteLine("OnStart");
        }

        protected override void OnSleep()
        {
            // Handle when your app sleeps
            Debug.WriteLine("OnSleep");
        }

        protected override void OnResume()
        {
            // Handle when your app resumes
            Debug.WriteLine("OnResume");
        }
    }
這份筆記的範例專案可以底下網址取得

Xamarin.Forms 的頁面事件

Xamarin.Forms 的頁面事件

了解更多關於 [Xamarin.Android] 的使用方式
了解更多關於 [Xamarin.iOS] 的使用方式
了解更多關於 [Xamarin.Forms] 的使用方式
了解更多關於 [Hello, Android:快速入門] 的使用方式
了解更多關於 [Hello, iOS – 快速入門] 的使用方式
了解更多關於 [Xamarin.Forms 快速入門] 的使用方式

在這份筆記中,將要來測試與分析頁面事件的呼叫順序;在 Xamarin.Forms 應用程式中,只要繼承了Page 類別的頁面,都會擁有這兩個事件可以使用:
  1. OnAppearing()
    您可以在頁面內的 code-behind 重新覆寫這個事件,當 Xamarin.Forms 頁面變成可見的時候,這個事件將會被呼叫。
  2. OnDisappearing()
    您可以在頁面內的 code-behind 重新覆寫這個事件,當 Xamarin.Forms 頁面變成不可見的時候,這個事件將會被呼叫。
因此,透過一個簡單的範例專案,在這個專案內,將會有兩個頁面,一個是 主頁面,另一個是 Page1頁面;這兩個頁面都有一個按鈕,前者頁面的按鈕按下之後,會切換到 Page1頁面 頁面,而後者頁面的按鈕按下之後,將會回到 主頁面;實際執行畫面如下圖所示。
ALM有導航1 ALM有導航2 ALM無導航
下面螢幕截圖,是在 iOS 系統內的執行情況
ALMiOS有導航1 ALMiOS有導航2
而每個頁面的 code-behind 中,將會有底下的程式碼;您將會看到,當要顯示這個頁面的時候,將會寫入訊息到除錯視窗內,而當不要再顯示這個頁面的時候,也會寫入訊息到除錯視窗內。
        protected override void OnAppearing()
        {
            Debug.WriteLine($"{this.Title} 進入到 OnAppearing");
            base.OnAppearing();
        }

        protected override void OnDisappearing()
        {
            Debug.WriteLine($"{this.Title} 進入到 OnDisappearing");
            base.OnDisappearing();
        }
不過,若您使用了 Prism 設計模式工具來開發 Xamarin.Forms 應用程式,除了在每個頁面的 code-behind 會有上述覆寫程式碼,在每個頁面相對應的檢視模型(ViewModel)內,也會實作 INavigationAware ˋ頁面的兩個方法:
  1. OnNavigatedFrom
    當進行頁面導航時候,需要離開這個頁面 (navigated away from),此時,這個方法將會被呼叫
  2. OnNavigatedTo
    當進行頁面導航時候,需要進入這個頁面 (navigated to),此時,這個方法將會被呼叫
因此,使用 Prism 設計模式工具開發的專案,當在進行頁面導航的時候,每個頁面將會有兩個事件會被呼叫到:
Page1 導航到 Page2
Page1 內的 OnDisappearing & OnNavigatedFrom 將會被呼叫
Page2 內的 OnAppearing & OnNavigatedTo 將會被呼叫
另外有一點特別要提到的是,當您採用了 Prism 設計模式工具,若您的進入點頁面是 ContentPage,則,一樣可以透過 Prism 來進行導航,如下圖所示。
ALM無導航1 ALM無導航2
所以,在 Prism 設計模式的專案內,將會進行兩個模式的測試:
  1. 進入點的頁面採用 ContentPage (請修改核心PCL 內的 App.xaml.cs 檔案內的 OnInitialized 方法)
    NavigationService.NavigateAsync("MainPage?title=Hello%20from%20Xamarin.Forms");
  2. 進入點的頁面採用 NavigationPage (請修改核心PCL 內的 App.xaml.cs 檔案內的 OnInitialized 方法)
    NavigationService.NavigateAsync("MainNavigationPage/MainPage?title=Hello%20from%20Xamarin.Forms");
這兩個測試頁面事件的範例專案,可以底下網址取得

實際執行結果

Xamarin.Forms 作法

底下是使用 XFALM 專案在 Android / iOS 模擬器上跑的結果
AndroidiOS
[0:] 主頁面 進入到 OnAppearing[0:] 主頁面 進入到 OnAppearing
[0:] 主頁面 進入到 OnDisappearing[0:] 主頁面 進入到 OnDisappearing
[0:] Page1頁面 進入到 OnAppearing[0:] Page1頁面 進入到 OnAppearing
[0:] Page1頁面 進入到 OnDisappearing[0:] Page1頁面 進入到 OnDisappearing
[0:] 主頁面 進入到 OnAppearing[0:] 主頁面 進入到 OnAppearing

Prism 作法 - 使用 ContentPage

底下是使用 XFPrismALM 專案在 Android / iOS 模擬器上跑的結果
AndroidiOS
[0:] 主頁面 進入到 OnNavigatedTo[0:] 主頁面 進入到 OnNavigatedTo
[0:] 主頁面 進入到 OnAppearing[0:] 主頁面 進入到 OnAppearing
[0:] 主頁面 進入到 OnNavigatedFrom[0:] 主頁面 進入到 OnNavigatedFrom
[0:] 主頁面 進入到 OnDisappearing[0:] Page1頁面 進入到 OnAppearing
[0:] Page1頁面 進入到 OnAppearing[0:] 主頁面 進入到 OnDisappearing
[0:] Page1頁面 進入到 OnNavigatedTo[0:] Page1頁面 進入到 OnNavigatedTo
[0:] Page1頁面 進入到 OnNavigatedFrom[0:] Page1頁面 進入到 OnNavigatedFrom
[0:] Page1頁面 進入到 OnDisappearing[0:] 主頁面 進入到 OnAppearing
[0:] 主頁面 進入到 OnNavigatedTo[0:] Page1頁面 進入到 OnDisappearing
[0:] 主頁面 進入到 OnAppearing[0:] 主頁面 進入到 OnNavigatedTo

Prism 作法 - 使用 NavigationPage

AndroidiOS
[0:] 主頁面 進入到 OnNavigatedTo[0:] 主頁面 進入到 OnNavigatedTo
[0:] 主頁面 進入到 OnAppearing[0:] 主頁面 進入到 OnAppearing
[0:] 主頁面 進入到 OnNavigatedFrom[0:] 主頁面 進入到 OnNavigatedFrom
[0:] 主頁面 進入到 OnDisappearing[0:] 主頁面 進入到 OnDisappearing
[0:] Page1頁面 進入到 OnAppearing[0:] Page1頁面 進入到 OnAppearing
[0:] Page1頁面 進入到 OnNavigatedTo[0:] Page1頁面 進入到 OnNavigatedTo
[0:] Page1頁面 進入到 OnNavigatedFrom[0:] Page1頁面 進入到 OnNavigatedFrom
[0:] Page1頁面 進入到 OnDisappearing[0:] Page1頁面 進入到 OnDisappearing
[0:] 主頁面 進入到 OnAppearing[0:] 主頁面 進入到 OnAppearing
[0:] 主頁面 進入到 OnNavigatedTo[0:] 主頁面 進入到 OnNavigatedTo

2016/08/15

Xamarin.Forms 版面配置選項 LayoutOptions

Xamarin.Forms 版面配置選項 LayoutOptions

在這份筆記中,將會描述與測試關於 LayoutOptions 這個結構物件的意義;在 XAML 的每個項目(element),例如:版面配置(Layout) 或者 控制項目內,都可以使用 HorizontalOptions 或者VerticalOptions 屬性(因為這兩個屬性定義在 View 類別內),並且透過兩個屬性定義,可以決定當時版面配置或者控制項會出現或這對齊哪個地方。
底下是 LayoutOptions 的定義,從底下結構定義的程式碼內,可以得知
  1. 當在 XAML 使用到有用到 HorizontalOptions 或者 VerticalOptions ,其定義的文字,會使用LayoutOptionsConverter 型別轉換器進行自動轉換,這也就是為什麼,您可以在 XAML 中,使用類似這樣的宣告 <Label Text="Welcome to Xamarin Forms!" VerticalOptions="Center"HorizontalOptions="Center" />
  2. 不論是 HorizontalOptions 或者 VerticalOptions 屬性,都可以設定沒有 Expand 的四種值或者有包含 Expand 的值。
  3. 若所指定的 LayoutOptions 沒有包含 Expand,表示這個項目要對其哪個地方;若有包含 Expand,表示這個項目要佔有剩下的空間,如果有的話。
這份筆記的範例專案可以底下網址取得
    //
    // 摘要:
    //     A struct whose static members define various alignment and expansion options.
    //
    // 備註:
    //     To be added.
    [TypeConverter(typeof(LayoutOptionsConverter))]
    public struct LayoutOptions
    {
        public static readonly LayoutOptions Center;
        public static readonly LayoutOptions CenterAndExpand;
        public static readonly LayoutOptions End;
        public static readonly LayoutOptions EndAndExpand;
        public static readonly LayoutOptions Fill;
        public static readonly LayoutOptions FillAndExpand;
        public static readonly LayoutOptions Start;
        public static readonly LayoutOptions StartAndExpand;

        public LayoutOptions(LayoutAlignment alignment, bool expands);

        public LayoutAlignment Alignment { get; set; }
        public bool Expands { get; set; }
    }

LayoutOptions 的意義(沒有 Expand)

  1. Start
    定義的項目將會往最上方(垂直模式) 或者 最左邊(水平模式) 對齊。
  2. Center
    定義的項目將會往中間(垂直模式 / 水平模式) 對齊。
  3. End
    定義的項目將會往最下方(垂直模式) 或者 最右邊(水平模式) 對齊。
  4. Fill
    這樣的定義與上述定位方式有些不同,這個項目將會延伸它的全部父項目 (Parent Element) 的大小。假使父項目所佔有的空間沒有比起他所有兒子項目來的大,您將不會看到有甚麼不同的對齊方式。這個設定項目,僅會在父項目擁有空間大於兒子項目的空間大小,才會有效果出現。

LayoutOptions 的意義(有 Expand)

若 LayoutOptions 的值後面有 Expand 文字,則表示當父項目的空間大於所有子項目所佔的空間,也就是說,當配置完所有的子項目之後,父項目還有多餘的空間;此時,XAML 系統會將剩下的空間,等比例的分配給有 Expand 的項目,而有 Expand 的子項目,將會佔據這些額外分配得到的空間,但是不需要將子項目填滿這些空間。
若 LayoutOptions 的值後面沒有 Expand 文字,就算父項目還有剩下的空間,它的子項目也不會獲得這些剩下的空間。
若父項目所擁有的空間沒有大於所有子項目所佔的空間總和,則就算有 Expand的值存在,也不會有任何效果產生。

範例執行成果

您可以實際下載這個範例專案來執行看看,並且按下每個按鈕,看看執行結果。
XFLayoutOptions
只要這些按鈕的父項目 StackLayout 沒有使用 Fill 屬性值,則這些按鈕的垂直版面配置選項是可以忽略的。
垂直版面配置選項只有當父項目 StackLayout 使用了 Fill 對其方式, 這樣父項目所擁有的空間就會大於所有子項目的空間,此時,若有使用了 Expand 的定義,這樣才會有所生效。