XAML 中的事件處理
建立 XAML UI 之後,您可以新增程式碼,回應使用者造訪頁面時發生的互動。 .NET MAUI 會透過標準 .NET 事件,通知應用程式使用者輸入和互動。
在本單元中,您將了解如何處理這些事件,並執行使用者預期的作業。
XAML 頁面中的命名元素
事件處理程式碼經常需要參考頁面上的特定控制項及其屬性。 您可以指派不重複的名稱給每個控制項。 若要進行此操作,請使用 XAML 屬性 x:Name
。 x: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
控制項可回應 Clicked
、Pressed
和 Released
事件,而 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;