共用方式為


開始使用 XAML

Browse sample.瀏覽範例。 瀏覽範例

在 .NET 多平臺應用程式 UI (.NET MAUI) 應用程式中,XAML 主要用於定義頁面的視覺內容,並與 C# 程式代碼後置檔案搭配運作。 後置程式碼檔案為標記提供支援程式碼。 這兩個檔案會共同參與新的類別定義,其中包含子檢視和屬性初始化。 在 XAML 檔案中,會使用 XML 元素和屬性來參考類別和屬性,並建立標記和程式代碼之間的連結。

XAML 檔案的結構

新的 .NET MAUI 應用程式包含三個 XAML 檔案,以及其相關聯的程式代碼後置檔案:

Screenshot of the structure of a new .NET MAUI app.新 .NET MAUI 應用程式結構的螢幕快照。

第一個檔案配對是 App.xaml、XAML 檔案,以及 App.xaml.cs與 XAML 檔案相關聯的 C# 程式代碼後置 檔案。 App.xaml 和 App.xaml.cs 共同構成一個從 Application 衍生的類別 App。 第二個檔案配對是 AppShell.xaml 和 AppShell.xaml.cs,它們參與定義一個名稱為 AppShell 的類別,該類別是從 Shell 衍生出來的。 大部分具有 XAML 檔案的其他類別都會參與衍生自 ContentPage的類別,並定義頁面的 UI。 這對MainPage.xamlMainPage.xaml.cs 檔案而言是事實。

MainPage.xaml 檔案的結構如下:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MyMauiApp.MainPage">
    ...
</ContentPage>

這兩個 XML 命名空間(xmlns)宣告指向 microsoft.com 上的 URI。 不過,這些 URI 沒有內容,而且基本上會作為版本標識符運作。

第一個 XML 命名空間宣告表示,在 XAML 檔案中定義且沒有前綴的標籤,像是 ContentPage,是指向 .NET MAUI 中的類別,例如ContentPage。 第二個命名空間宣告定義了一個 x 的前綴。 這用於 XAML 本身內建的數個元素和屬性,以及 XAML 的其他實作所支援的屬性。 不過,這些元素和屬性會根據 URI 中內嵌的年份而略有不同。 .NET MAUI 支援 2009 XAML 規格

在第一個標記的結尾,x 前綴用於名為 Class 的屬性。 由於此 x 前綴幾乎適用於 XAML 命名空間,因此 XAML 屬性如 Class 幾乎總是被稱為 x:Classx:Class 屬性指定完整修飾的 .NET 類別名稱:MyMauiApp 命名空間中的 MainPage 類別。 這表示這個 XAML 檔案定義了一個在 MyMauiApp 命名空間中名為 MainPage 的新類別,該類別衍生自 ContentPagex:Class 屬性所在的標記)。

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

MainPage.xaml.cs 檔案看起來是這樣的:

namespace MyMauiApp;

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

MainPage 類別 衍生自 ContentPage,並且是 部分類別 定義。

當 Visual Studio 建置專案時,來源產生器會產生新的 C# 來源,其中包含從InitializeComponent方法呼叫的MainPage建構函式的定義,並將它新增至編譯物件。

在執行時,MauiProgram 類別中的程式碼會初始化應用程式並執行 App 類別的建構函式,從而具現化 AppShell。 類別 AppShell 負責實例化應用程式要顯示的第一頁,那就是 MainPage。 建構子 MainPage 會呼叫 InitializeComponent,它會初始化在 XAML 檔案中定義的所有物件,將它們全部連接成父子關係,將程式碼中定義的事件處理常式附加到 XAML 檔案中設定的事件,並將物件生成的樹形結構設定為頁面的內容。

注意

AppShell 類別使用 .NET MAUI Shell 來設定應用程式的首頁顯示。 不過,Shell 超出此 XAML 簡介的範圍。 如需詳細資訊,請參閱 .NET MAUI Shell

設定頁面內容

ContentPage應該包含一個子元素,可以是檢視或提供子檢視的版面配置。 ContentPage 的子系會自動被設定為 ContentPage.Content 屬性的值。

下列範例顯示 ContentPage 包含 的 Label

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.HelloXamlPage"
             Title="Hello XAML Page">
    <Label Text="Hello, XAML!"
           VerticalOptions="Center"
           HorizontalTextAlignment="Center"
           Rotation="-15"
           FontSize="18"
           FontAttributes="Bold"
           TextColor="Blue" />
</ContentPage>

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

有許多快捷方式可用來設定這些屬性的值。 有些屬性是基本數據類型。 例如,TitleText 屬性的類型為 string,且 Rotation 的類型為 doubleHorizontalTextAlignment 屬性是 TextAlignment 類型,這是一個枚舉。 對於任何列舉型別的屬性,您只需要提供成員名稱。

不過,對於更複雜的型別屬性,轉換器會用於剖析 XAML。 這些是 .NET MAUI 中繼承自TypeConverter的類別。 針對上述範例,會自動套用數個 .NET MAUI 轉換器,將字串值轉換成正確的類型:

  • LayoutOptionsConverterVerticalOptions 屬性。 這個轉換器會將 LayoutOptions 結構之公用靜態欄位的名稱轉換為 LayoutOptions 類型的值。
  • LayoutOptionsConverter 用於 VerticalOptions 屬性。 此轉換子會轉換類別或十六進位 RGB 值的公用靜態欄位 Colors 名稱,以及具有或不含 Alpha 色板。

當您執行 .NET MAUI 應用程式時, MainPage 通常會顯示 。 若要查看不同的頁面,您可以將該頁面設定為 AppShell.xaml 檔案中的新啟動頁面,或從位於的地方流覽至新頁面。

若要實作導航,請在 MainPage.xaml.cs 建構函式中,建立一個簡單的按鈕,並使用事件處理程式來巡覽至 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;
}

當您編譯及部署此應用程式的新版本時,畫面上會出現一個按鈕。 按下它將導航至HelloXamlPage

Screenshot of rotated Label text.旋轉標籤文字的螢幕快照。

您可以使用於各平台中出現的導覽列來導覽回到 MainPage

注意

此流覽模型的替代方法是使用 .NET MAUI Shell。 如需詳細資訊,請參閱 .NET MAUI Shell 概述

XAML 和程式代碼互動

大部分 ContentPage 衍生專案的子系是版面配置,例如 StackLayoutGrid,而且版面配置可以包含多個子系。 在 XAML 中,這些父子式關聯性是使用一般 XML 階層建立的:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.XamlPlusCodePage"
             Title="XAML + Code Page">
    <StackLayout>
        <Slider VerticalOptions="Center" />
        <Label Text="A simple Label"
               FontSize="18"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <Button Text="Click Me!"
                HorizontalOptions="Center"
                VerticalOptions="Center" />
    </StackLayout>
</ContentPage>

此 XAML 檔案是語法完整的,併產生下列 UI:

Screenshot of multiple controls on a page.頁面上多個控制項的螢幕快照。

不過,雖然您可以與 Slider 和 Button 互動,但使用者介面 (UI) 並不會更新。 Slider 應該會讓 Label 顯示目前的值,而 Button 應該執行某些動作。

Slider 透過 Label,可以完全在 XAML 中使用 資料繫結 來顯示數值。 不過,先查看程式代碼解決方案會很有用。 即便如此,處理 Button 點擊肯定需要代碼。 這表示,XamlPlusCodePage 的程式代碼後置檔案必須包含 ValueChangedSlider事件處理程式,和 ClickedButton事件處理程式:

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

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

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

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

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

回到 XAML 檔案,需要在 SliderButton 標記中加入屬性,以包含 ValueChangedClicked 事件,這些事件參考了這些處理程式。

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="XamlSamples.XamlPlusCodePage"
             Title="XAML + Code Page">
    <StackLayout>
        <Slider VerticalOptions="Center"
                ValueChanged="OnSliderValueChanged" />
        <Label x:Name="valueLabel"
               Text="A simple Label"
               FontSize="18"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <Button Text="Click Me!"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Clicked="OnButtonClicked" />
    </StackLayout>
</ContentPage>

請注意,將處理程式指派給事件具有與將值指派給屬性相同的語法。 此外,若要在 Slider 事件處理程式中使用 Label 來顯示目前值,處理程式必須從程式碼中參考該物件。 因此,Label 需要一個名稱,這由 x:Name 屬性指定。 屬性 的 前置詞表示這個屬性是 XAML 本身的。 您指派給 x:Name 屬性的名稱與 C# 變數名稱具有相同的規則。 例如,它必須以字母或底線開頭,且不包含內嵌空格。

ValueChanged事件處理程式現在可以設定Label來顯示新的Slider值,而這個值可從事件參數取得:

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

或者,處理程式也可以從 sender 參數中取得正在產生此事件的 Slider 物件,然後從該物件中取得 Value 屬性:

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

結果是,對Slider的任何操作都會使其值顯示在Label中。

頁面上多個控制項的螢幕擷取畫面,其中顯示滑動條的值。

在上述範例中,透過顯示警示來模擬事件的回應,並在警示中顯示按鈕的。 因此,事件處理程式可以將 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");
}

方法OnButtonClicked的定義是async,因為DisplayAlert方法是異步的,應該使用await關鍵字來前置,該關鍵字會在方法完成時返回。 因為這個方法透過從 參數 取得 按鈕觸發事件,所以同一個處理程式可用於多個按鈕。

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

方法OnButtonClicked的定義是async,因為DisplayAlertAsync方法是異步的,應該以await運算符作為前綴,這個運算符會在方法完成時返回。 因為這個方法會從 sender 參數中取得觸發事件的物件,所以可以對多個按鈕使用同一個處理程式。

下一步

XAML 主要是針對具現化和初始化對象所設計。 但是,屬性通常必須設定為無法輕易表示為 XML 字串的複雜物件,而某個類別所定義的屬性有時必須在子類別上設定。 這兩個需求需要基本的 XAML 語法功能:屬性元素附加屬性