XAML 中的事件處理

已完成

建立 XAML UI 之後,您可以新增程式碼,回應使用者造訪頁面時發生的互動。 .NET MAUI 會透過標準 .NET 事件,通知應用程式使用者輸入和互動。

在本單元中,您將了解如何處理這些事件,並執行使用者預期的作業。

XAML 頁面中的命名元素

事件處理程式碼經常需要參考頁面上的特定控制項及其屬性。 您可以指派不重複的名稱給每個控制項。 若要進行此操作,請使用 XAML 屬性 x:Namex:Name 屬性會執行兩個動作︰

  • 將一個私人欄位新增至所產生且對應至此元素的程式碼後置檔案。 使用程式碼中的此欄位來與視覺元素互動,以設定執行階段屬性及處理事件。

  • 如此,XAML 即可透過此名稱辨識元素。 您可以從在相同 XAML 檔案中定義的其他元素參考這些元素。

當您為元素命名時,無法使用任何任意字串。 指派給 x:Name 屬性的值會用來在程式碼中建立欄位。 取而代之的是,它必須符合變數的命名慣例。 此外,名稱會編譯到程式碼後置定義中,因此也必須是唯一的。

在您為元素提供名稱之後,即可在程式碼後置檔案中與該元素互動。 以下 XAML 片段定義 Label 控制項。 命名為 CounterLabel (此範例取自 .NET MAUI 範本產生的預設應用程式):

    <Label Text="Current count: 0"
        ...
        x:Name="CounterLabel"
        ... />

在此頁面的程式碼後置中,您可以透過 CounterLabel 欄位參考此控制項,並修改其屬性:

count++;
CounterLabel.Text = $"Current count: {count}";

重要

在執行頁面的 InitializeComponent 方法之前,不會初始化欄位。 此方法是 XAML 剖析和物件具現化程序的一部分。 請將與以 XAML 定義之元素互動的任何程式碼放在此呼叫之後。 此規則的例外是 ContentPage 類別本身。 您可以在 InitializeComponent 方法執行之前,存取類別上的所有屬性。 不過,如果您使用 XAML 在此類別上設定任何屬性,執行 InitializeComponent 前,這些屬性值將會覆寫您可能已設定的任何值。

使用屬性來連接事件

許多控制項會公開屬性,其對應至這些控制項可回應的事件,例如按鈕的 Clicked 事件。 不同的控制項支援不同的事件集。 例如,Button 控制項可回應 ClickedPressedReleased 事件,而 Entry 控制項則有 TextChanged 等事件。 您可以在頁面的 XAML 標記中初始化事件屬性,並指定事件觸發時要執行的方法名稱。 事件方法必須符合下列簽章需求:

  • 無法傳回值,方法須為 void
  • 需有兩個參數,object 參考,表示觸發事件的物件 (稱為「傳送者」),以及 EventArgs 參數,其中包含傳送者傳遞至事件處理常式的任何引數。
  • 事件處理常式應為 private。 這並非強制,但如果您將事件處理常式設為公開,外部便可存取,而且可能會由觸發之預期事件以外的動作叫用。
  • 如果必須執行非同步作業,事件處理常式可為 async

以下範例說明 .NET MAUI 範本範例應用程式中按鈕的 Clicked 事件處理常式定義。 方法的名稱遵循標準慣例,On 後面接著控制項名稱 (按鈕名為 Counter),以及事件名稱 (Clicked)。 此慣例並非強制,但為好的做法:

private void OnCounterClicked(object sender, EventArgs e)
{
    ...
}

關注點分離

在 XAML 中連接事件相當方便,但其會將控制項行為與 UI 定義混合。 許多開發人員都偏好區別那些元素,並在程式碼後置中針對具名元素進行所有事件處理常式訂閱。 這會讓檢視連接情況及行為對應對象變得較為容易。 此方法也會降低在不自覺的情況下移除 XAML 中的處理常式,而意外中斷程式碼之情況的發生機率。 編譯器不會攔截移除的處理常式,只有在程式碼無法正確執行該行為時,這才會成為問題。

無論您選擇使用 XAML 或使用程式碼來連接事件處理常式,都是個人選擇。

若要在程式碼中連接事件處理常式,請使用 += 運算子來訂閱事件。 您通常會在呼叫 InitializeComponent 之後,在頁面的建構函式中執行此作業:

public partial class MainPage : ContentPage, IPage
{
    public MainPage()
    {
        InitializeComponent();
        Counter.Clicked += OnCounterClicked;
    }

    ...

    private void OnCounterClicked(object sender, EventArgs e)
    {
        ...
    }
}

注意

您可以使用此方法,為同一個事件訂閱多個事件處理方法。 每個事件處理方法都會在事件發生時執行,但您不應假設這些方法會以任何特定順序執行,因此請勿讓它們之間產生相依性。

同樣地,您也可以稍後在應用程式中,使用 -= 運算子,從事件中取消訂閱事件處理常式,藉此移除:

Counter.Clicked -= OnCounterClicked;

知識檢查

1.

哪些參數傳遞至事件處理方法?

2.

您可以使用哪個運算子,將事件處理常式連接至 C# 中的事件?