共用方式為


第 1 部份: 開始使用 XAML

Xamarin.Forms在應用程式中,XAML 主要用於定義頁面的視覺內容,並與 C# 程式代碼後置檔案搭配運作。

程序代碼後置檔案提供標記的程式代碼支援。 這兩個檔案會共同參與新的類別定義,其中包含子檢視和屬性初始化。 在 XAML 檔案中,會使用 XML 元素和屬性來參考類別和屬性,並建立標記和程式代碼之間的連結。

建立方案

若要開始編輯您的第一個 XAML 檔案,請使用 Visual Studio 或 Visual Studio for Mac 來建立新的 Xamarin.Forms 解決方案。 (選取下方對應至您環境的索引標籤。

在 Windows 中,啟動 Visual Studio 2019,然後在 [開始] 視窗中,按兩下 [建立新專案] 以建立新的專案

新增方案視窗

在 [建立新專案] 視窗中,選取 [專案類型] 下拉式清單中的 [行動裝置],選取 [行動應用程式]Xamarin.Forms 範本,然後按兩下 [下一步] 按鈕:

新增項目視窗

在 [設定新專案] 視窗中,將 [專案名稱] 設定為 [XamlSamples] (或您偏好的任何專案),然後按兩下 [建立] 按鈕。

在 [ 新增跨平臺應用程式 ] 對話框中,按兩下 [ 空白],然後按下 [ 確定] 按鈕:

新增應用程式對話框

解決方案中會建立四個專案:XamlSamples .NET Standard 連結庫、XamlSamples.AndroidXamlSamples.iOS 和 通用 Windows 平台 方案 XamlSamples.UWP

建立 XamlSamples 解決方案之後,您可以選取各種平臺專案作為方案啟動專案,並在手機模擬器或實際裝置上建置和部署專案範本所建立的簡單應用程式,以測試開發環境。

除非您需要撰寫平臺特定的程式代碼,否則共用 的 XamlSamples .NET Standard 連結庫專案就是您將花費幾乎所有程式設計時間的地方。 這些文章不會冒險到該專案之外。

XAML 檔案的結構

在 XamlSamples .NET Standard 連結庫中,有一組具有下列名稱的檔案:

  • App.xaml,XAML 檔案;和
  • App.xaml.cs,與 XAML 檔案相關聯的 C# 程式代碼後置檔案。

您必須按兩下 App.xaml的箭號,才能查看程式代碼後置檔案。

App.xamlApp.xaml.cs都會參與衍生自 Application的類別App 大部分具有 XAML 檔案的其他類別都會參與衍生自 ContentPage的類別;這些檔案會使用 XAML 來定義整個頁面的視覺內容。 這是 XamlSamples 專案中其他兩個檔案的 true:

  • MainPage.xaml,XAML 檔案;和
  • MainPage.xaml.cs,C# 程式代碼後置檔案。

MainPage.xaml 檔案看起來像這樣(雖然格式可能稍有不同):

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:XamlSamples"
             x:Class="XamlSamples.MainPage">

    <StackLayout>
        <!-- Place new controls here -->
        <Label Text="Welcome to Xamarin Forms!"
               VerticalOptions="Center"
               HorizontalOptions="Center" />
    </StackLayout>

</ContentPage>

這兩個 XML 命名空間 (xmlns) 宣告是指 URI,第一個似乎在 Xamarin 的網站上,第二個似乎是Microsoft。 不要費心檢查這些 URI 指向什麼。 那裡沒有什麼。 它們只是 Xamarin 和 Microsoft所擁有的 URI,而且基本上會作為版本識別碼運作。

第一個 XML 命名空間宣告表示在 XAML 檔案中定義的標籤沒有前置詞, Xamarin.Forms例如 ContentPage。 第二個命名空間宣告會定義的 x前置詞。 這用於 XAML 本身內建的數個元素和屬性,以及 XAML 的其他實作所支援的屬性。 不過,這些元素和屬性會根據 URI 中內嵌的年份而略有不同。 Xamarin.Forms 支援 2009 XAML 規格,但並非全部。

local命名空間宣告可讓您從 .NET Standard 連結庫專案存取其他類別。

在第一個標記的結尾,前置 x 詞會用於名為 Class的屬性。 由於此 x 前置詞的使用幾乎適用於 XAML 命名空間,因此 Class XAML 屬性幾乎一律稱為 x:Class

屬性 x:Class 會指定完整 .NET 類別名稱: MainPage 命名空間中的 XamlSamples 類別。 這表示這個 XAML 檔案會在衍生自 ContentPage的命名空間中XamlSamples定義名為 MainPage 的新類別,也就是屬性出現所在的x:Class標記。

屬性 x:Class 只能出現在 XAML 檔案的根元素中,以定義衍生的 C# 類別。 這是 XAML 檔案中唯一定義的新類別。 XAML 檔案中出現的所有其他專案,只是從現有的類別具現化並初始化。

MainPage.xaml.cs檔案看起來像這樣(除了未使用的using指示詞外):

using Xamarin.Forms;

namespace XamlSamples
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
        }
    }
}

類別 MainPage 衍生自 ContentPage,但請注意 partial 類別定義。 這表示應該有另一個 的部分類別定義, MainPage但該定義在哪裡? 這個方法是什麼 InitializeComponent

當 Visual Studio 建置專案時,它會剖析 XAML 檔案以產生 C# 程式代碼檔案。 如果您在 XamlSamples\XamlSamples\obj\Debug 目錄中尋找名為 XamlSamples.MainPage.xaml.g.cs 的檔案。 'g' 代表產生的 。 這是的另一個部分類別定義MainPage,其中包含從MainPage建構函式呼叫的方法定義InitializeComponent。 然後,這兩個部分 MainPage 類別定義可以一起編譯。 根據 XAML 是否已編譯,XAML 檔案或 XAML 檔案的二進位格式會內嵌在可執行檔中。

在運行時間,特定平台專案中的程式代碼會呼叫 LoadApplication 方法,並傳遞至 .NET Standard 連結庫中 類別的新實例 App 。 類別建構函式會 App 具現化 MainPage。 該類別的建構函式會呼叫 InitializeComponent,然後呼叫 LoadFromXaml 方法,從 .NET Standard 連結庫擷取 XAML 檔案(或其編譯的二進位檔)。 LoadFromXaml 初始化 XAML 檔案中定義的所有物件、將它們全部連接在父子關聯性中、將程式代碼中定義的事件處理程式附加至 XAML 檔案中設定的事件,並將對象的結果樹狀結構設定為頁面的內容。

雖然您通常不需要花太多時間處理產生的程式代碼檔案,但有時候產生的檔案中的程式代碼上會引發運行時間例外狀況,因此您應該熟悉它們。

當您編譯並執行此程式時, Label 元素會出現在頁面中央,如 XAML 建議:

默認 Xamarin.Forms 顯示

如需更有趣的視覺效果,您只需要更有趣的 XAML。

新增 XAML 頁面

若要將其他 XAML 型ContentPage類別新增至您的專案,請選取 XamlSamples .NET Standard 連結庫專案,以滑鼠右鍵按兩下,然後選取 [新增>專案...]。在 [新增專案] 對話框中,選取 [Visual C# 專案>>Xamarin.Forms內容頁面] (而非 [內容頁面 ][C#],這會建立僅限程序代碼的頁面,或不是頁面的內容檢視)。 提供頁面名稱,例如 HelloXamlPage

新增項目對話框

兩個檔案會新增至專案 HelloXamlPage.xaml 和程式代碼後置檔案 HelloXamlPage.xaml.cs

設定頁面內容

編輯 HelloXamlPage.xaml 檔案,讓唯一的標籤是 和 ContentPage.ContentContentPage標籤:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.HelloXamlPage">
    <ContentPage.Content>

    </ContentPage.Content>
</ContentPage>

標籤 ContentPage.Content 是 XAML 唯一語法的一部分。 起初,它們看起來可能無效,但它們是合法的。 句點不是 XML 中的特殊字元。

標籤 ContentPage.Content屬性項目 標記。 Content 是 的 ContentPage屬性,通常設定為單一檢視或具有子檢視的配置。 一般而言,屬性會變成 XAML 中的屬性,但很難將屬性設定 Content 為複雜物件。 因此,屬性會以 XML 專案表示,其中包含類別名稱和以句號分隔的屬性名稱。 Content現在可以在標記之間ContentPage.Content設定 屬性,如下所示:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.HelloXamlPage"
             Title="Hello XAML Page">
    <ContentPage.Content>

        <Label Text="Hello, XAML!"
               VerticalOptions="Center"
               HorizontalTextAlignment="Center"
               Rotation="-15"
               IsVisible="true"
               FontSize="Large"
               FontAttributes="Bold"
               TextColor="Blue" />

    </ContentPage.Content>
</ContentPage>

另請注意, Title 已在根標記上設定屬性。

此時,類別、屬性和 XML 之間的關聯性應該很明顯: Xamarin.Forms 類別 (例如 ContentPageLabel) 會以 XML 元素的形式出現在 XAML 檔案中。 該類別的屬性,包括 Title on ContentPage 和 7 屬性 Label,通常會顯示為 XML 屬性。

有許多快捷方式可用來設定這些屬性的值。 某些屬性是基本資料類型:例如,Title和 屬性的類型為 StringRotation ,屬於 類型 Double,且 IsVisibletrue預設為 ,且僅針對圖例設定在這裡) 的類型為 BooleanText

屬性 HorizontalTextAlignment 的類型為 TextAlignment,這是列舉。 對於任何列舉型別的屬性,您只需要提供的成員名稱。

不過,對於更複雜的型別屬性,轉換器會用於剖析 XAML。 這些是衍生自TypeConverter的Xamarin.Forms類別。 許多是公用類別,但有些不是。 針對這個特定的 XAML 檔案,這些類別中有數個會在幕後扮演角色:

  • LayoutOptionsConverter屬性的VerticalOptions
  • FontSizeConverter屬性的FontSize
  • ColorTypeConverter屬性的TextColor

這些轉換器會控管屬性設定的允許語法。

ThicknessTypeConverter可以處理以逗號分隔的一、二或四個數位。 如果提供一個數位,則會套用至所有四面。 使用兩個數位時,第一個是左右邊框間距,第二個是頂端和底部。 四個數位依左、上、右和下的順序排列。

LayoutOptionsConverter可以將 結構之公用靜態字段LayoutOptions的名稱轉換為 類型的LayoutOptions值。

FontSizeConverter可以處理NamedSize成員或數值字型大小。

接受 ColorTypeConverter 結構或十六進位 RGB 值之公用靜態欄位 Color 的名稱,且前面加上數字符號 (#) 或不含 Alpha 色板。 以下是沒有Alpha通道的語法:

TextColor="#rrggbb"

每個小字母都是十六進位數位。 以下是包含 Alpha 色板的方式:

TextColor="#aarrggbb">

對於Alpha色板,請記住FF完全不透明,00完全透明。

另外兩種格式可讓您為每個通道指定一個十六進位數位:

TextColor="#rgb" TextColor="#argb"

在這些情況下,會重複數位以形成值。 例如,#CF3 是 RGB 色彩 CC-FF-33。

當您執行 XamlSamples 程式時, MainPage 會顯示 。 若要查看新的 HelloXamlPage ,您可以將該設定為 App.xaml.cs 檔案中的新啟動頁面,或從 MainPage流覽至新頁面。

若要實作導覽,請先變更App.xaml.cs建構函式中的程序代碼,NavigationPage以便建立物件:

public App()
{
    InitializeComponent();
    MainPage = new NavigationPage(new MainPage());
}

在MainPage.xaml.cs建構函式中,您可以建立簡單的 Button ,並使用事件處理程式巡覽至 HelloXamlPage

public MainPage()
{
    InitializeComponent();

    Button button = new Button
    {
        Text = "Navigate!",
        HorizontalOptions = LayoutOptions.Center,
        VerticalOptions = LayoutOptions.Center
    };

    button.Clicked += async (sender, args) =>
    {
        await Navigation.PushAsync(new HelloXamlPage());
    };

    Content = button;
}

設定 Content 頁面的 屬性會取代 XAML 檔案中的 屬性設定 Content 。 當您編譯及部署這個程式的新版本時,畫面上會出現一個按鈕。 按會巡覽至 HelloXamlPage。 以下是iPhone、Android和UWP上的結果頁面:

旋轉標籤文字

您可以使用 iOS 上的 [上一頁] 按鈕,使用頁面頂端或 Android 手機底部的向左箭號,或使用 Windows 10 頁面上頂端的向左箭號來流覽MainPage<

您可以隨意試驗 XAML,以取得轉譯 Label的不同方式。 如果您需要將任何 Unicode 字元內嵌到文字中,您可以使用標準 XML 語法。 例如,若要將問候語放在智慧引號中,請使用:

<Label Text="&#x201C;Hello, XAML!&#x201D;" … />

外觀大致如下:

使用 Unicode 字元旋轉標籤文字

XAML 和程式代碼互動

HelloXamlPage 範例只包含頁面上的單Label一,但這是非常不尋常的。 大部分 ContentPage 的衍生專案會將 Content 屬性設定為某種類型的版面配置,例如 StackLayout。 的 Children StackLayout 屬性定義為 型 IList<View> 別,但它實際上是 類型的 ElementCollection<View>物件,而且該集合可以填入多個檢視或其他版面配置。 在 XAML 中,這些父子式關聯性是使用一般 XML 階層建立的。 以下是名為 XamlPlusCodePage 之新頁面的 XAML 檔案:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.XamlPlusCodePage"
             Title="XAML + Code Page">
    <StackLayout>
        <Slider VerticalOptions="CenterAndExpand" />

        <Label Text="A simple Label"
               Font="Large"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <Button Text="Click Me!"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand" />
    </StackLayout>
</ContentPage>

此 XAML 檔案是語法完整的,以下是其外觀:

頁面上的多個控件

不過,您可能會將此程式視為功能不足。 也許 Slider 應該會導致 Label 顯示目前值,而 Button 可能打算在程式內執行某些動作。

如您在第 4 部分中所見。數據系結基本概念,使用 Label 來顯示Slider值的作業可以透過數據系結在 XAML 中完全處理。 但先查看程式程式碼解決方案會很有用。 即便如此,處理 Button 點擊肯定需要程序代碼。 這表示的程式代碼後置檔案XamlPlusCodePage必須包含 之 事件的Slider處理程式ValueChanged,以及 ClickedButton事件。 讓我們新增它們:

namespace XamlSamples
{
    public partial class XamlPlusCodePage
    {
        public XamlPlusCodePage()
        {
            InitializeComponent();
        }

        void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
        {

        }

        void OnButtonClicked(object sender, EventArgs args)
        {

        }
    }
}

這些事件處理程式不需要是公用的。

回到 XAML 檔案, SliderButton 標記必須包含參考這些處理程式之 ValueChangedClicked 事件的屬性:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.XamlPlusCodePage"
             Title="XAML + Code Page">
    <StackLayout>
        <Slider VerticalOptions="CenterAndExpand"
                ValueChanged="OnSliderValueChanged" />

        <Label Text="A simple Label"
               Font="Large"
               HorizontalOptions="Center"
               VerticalOptions="CenterAndExpand" />

        <Button Text="Click Me!"
                HorizontalOptions="Center"
                VerticalOptions="CenterAndExpand"
                Clicked="OnButtonClicked" />
    </StackLayout>
</ContentPage>

請注意,將處理程式指派給事件具有與將值指派給屬性相同的語法。

如果 事件的Slider處理程式ValueChanged將使用 Label 來顯示目前值,處理程式就必須從程式代碼參考該物件。 需要 Label 以 屬性指定 x:Name 的名稱。

<Label x:Name="valueLabel"
       Text="A simple Label"
       Font="Large"
       HorizontalOptions="Center"
       VerticalOptions="CenterAndExpand" />

屬性 xx:Name 前置詞表示這個屬性是 XAML 內建的。

您指派給 x:Name 屬性的名稱與 C# 變數名稱具有相同的規則。 例如,它必須以字母或底線開頭,且不包含內嵌空格。

ValueChanged現在事件處理程式可以設定 Label 來顯示新Slider值。 新的值可從事件自變數取得:

void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
    valueLabel.Text = args.NewValue.ToString("F3");
}

或者,處理程式可以從 自變數取得 Slider 產生此事件 sender 的物件,並從中取得 Value 屬性:

void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
    valueLabel.Text = ((Slider)sender).Value.ToString("F3");
}

當您第一次執行程式時, Label 不會顯示 Slider 值,因為 ValueChanged 事件尚未引發。 但是,任何操作 Slider 都會顯示值:

顯示滑桿值

現在針對 Button。 讓我們藉由顯示具有 按鈕的警示Text來模擬事件的回應Clicked。 事件處理程式可以安全地將 自變數Button轉換成 sender ,然後存取其屬性:

async void OnButtonClicked(object sender, EventArgs args)
{
    Button button = (Button)sender;
    await DisplayAlert("Clicked!",
        "The button labeled '" + button.Text + "' has been clicked",
        "OK");
}

方法的定義是 async ,因為 DisplayAlert 方法是異步的 await ,而且應該以 運算符開頭,這個運算符會在方法完成時傳回。 因為這個方法會 Buttonsender 自變數取得引發事件,所以同一個處理程式可用於多個按鈕。

您已看到在 XAML 中定義的物件可以引發程式代碼後置檔案中處理的事件,而且程式代碼後置檔案可以使用指派給 x:Name 它與 屬性的名稱來存取 XAML 中定義的物件。 這些是程式代碼和 XAML 互動的兩種基本方式。

藉由檢查新產生的 XamlPlusCode.xaml.g.cs檔案來收集 XAML 運作方式的一些額外見解,該檔案現在包含指派給任何屬性做為私人字段的任何 x:Name 名稱。 以下是該檔案的簡化版本:

public partial class XamlPlusCodePage : ContentPage {

    private Label valueLabel;

    private void InitializeComponent() {
        this.LoadFromXaml(typeof(XamlPlusCodePage));
        valueLabel = this.FindByName<Label>("valueLabel");
    }
}

此欄位的宣告可讓變數自由使用您管轄範圍內部分類別檔案內 XamlPlusCodePage 的任何位置。 在運行時間,欄位會在剖析 XAML 之後指派。 這表示valueLabel欄位是在null建構函式開始時,但在呼叫 之後InitializeComponent有效時XamlPlusCodePage

將控件傳回建構函式之後 InitializeComponent ,頁面的視覺效果就如同已在程式代碼中具現化和初始化一樣建構。 XAML 檔案不再在 類別中扮演任何角色。 例如,您可以將檢視新增至 ,或將頁面的 屬性完全設定ContentStackLayout其他物件,以任何您想要的方式操作頁面上的物件。 您可以檢查頁面的 屬性和版面配置集合中的Children專案,以「逐步執行Content樹狀結構」。 您可以在以這種方式存取的檢視上設定屬性,或動態指派事件處理程式給它們。

自由自在。 它是您的頁面,而 XAML 只是建置其內容的工具。

摘要

在此簡介中,您已瞭解 XAML 檔案和程式代碼檔案如何參與類別定義,以及 XAML 和程式代碼檔案的互動方式。 但 XAML 也有它自己的獨特語法功能,允許它以非常靈活的方式使用。 您可以在第 2 部分開始探索這些專案 。基本 XAML 語法