路由事件概觀 (WPF .NET)
Windows Presentation Foundation (WPF) 應用程式開發人員和元件作者可以使用路由事件,透過元素樹狀結構傳播事件,並在樹狀結構中的多個接聽程式上叫用事件處理常式。 通用語言執行平台 (CLR) 事件中不提供這些功能。 數個 WPF 事件是路由事件,例如 ButtonBase.Click (部分機器翻譯)。 本文討論基本的路由事件概念,並提供何時及如何回應路由事件的指引。
必要條件
本文假設您對通用語言執行平台 (CLR)、物件導向程式設計,以及如何將 WPF 元素版面配置概念化為樹狀結構有基本了解。 若要遵循本文中的範例,建議您先熟悉 Extensible Application Markup Language (XAML),並了解如何撰寫 WPF 應用程式 (部分機器翻譯)。
什麼是路由事件?
您可以從功能或實作觀點來考量路由事件:
從功能觀點來看,路由事件是一種事件類型,可在元素樹狀結構中的多個接聽程式上叫用處理常式,而不只是在事件來源上。 事件接聽程式是附加和叫用事件處理常式所在的元素。 事件來源是原本引發事件的元素或物件。
從實作觀點來看,路由事件是向 WPF 事件系統註冊的事件,由 RoutedEvent (英文) 類別的執行個體所支援,並由 WPF 事件系統處理。 一般而言,路由事件是使用 CLR 事件「包裝函式」來實作,以啟用在 XAML 和程式碼後置中附加處理常式,就像 CLR 事件一樣。
WPF 應用程式通常包含許多元素,這些元素是在 XAML 中宣告或在程式碼中具現化。 應用程式的元素存在於其元素樹狀結構中。 根據路由事件的定義方式,在來源元素上引發事件時,其會:
- 在元素樹狀結構中從來源元素到根元素 (通常是頁面或視窗) 進行事件反昇。
- 在元素目樹狀結構中從根元素到來源元素往下進行通道處理。
- 不周遊元素樹狀結構,而只會發生在來源元素上。
考慮下列部分元素樹狀結構:
<Border Height="30" Width="200" BorderBrush="Gray" BorderThickness="1">
<StackPanel Background="LightBlue" Orientation="Horizontal" Button.Click="YesNoCancelButton_Click">
<Button Name="YesButton">Yes</Button>
<Button Name="NoButton">No</Button>
<Button Name="CancelButton">Cancel</Button>
</StackPanel>
</Border>
元素樹狀結構會轉譯,如下所示:
這三個按鈕中的每一個都是潛在的 Click (部分機器翻譯) 事件來源。 按兩下其中一個按鈕時,其會引發從按鈕到根元素事件反昇的 Click
事件。
Button (部分機器翻譯) 和 Border (部分機器翻譯) 元素未附加事件處理常式,但 StackPanel (部分機器翻譯) 有。 樹狀結構中可能較高且未顯示的其他元素也附加了 Click
事件處理常式。 當 Click
事件到達 StackPanel
元素時,WPF 事件系統會叫用附加至它的 YesNoCancelButton_Click
處理常式。 範例中 Click
事件的事件路由為:Button
->StackPanel
->Border
-> 連續父元素。
注意
原本引發路由事件的元素會識別為事件處理常式參數中的 RoutedEventArgs.Source (英文)。 事件接聽程式是附加和叫用事件處理常式所在的元素,而且會識別為事件處理常式參數中的傳送者 (部分機器翻譯)。
路由事件的最上層案例
以下是一些促使路由事件概念,並將它與典型 CLR 事件區分的案例:
控制項組合和封裝:WPF 中的各種控制項都有豐富的內容模型。 例如,您可以將影像放在 Button (部分機器翻譯) 內,這可有效地延伸按鈕的視覺化樹狀結構。 但是,新增的影像不得中斷按鈕的點擊測試行為,其必須在使用者按下影像像素時做出回應。
單一處理常式附件點:您可以為每個按鈕的
Click
事件註冊處理常式,但使用路由事件時,您可以附加單一處理常式,如上一個 XAML 範例所示。 這可讓您變更單一處理常式底下的元素樹狀結構,例如新增或移除更多按鈕,而不需要註冊每個按鈕的Click
事件。 引發Click
事件時,處理常式邏輯可以判斷事件的來源。 在先前顯示的 XAML 元素樹狀結構中指定的下列處理常式包含該邏輯:private void YesNoCancelButton_Click(object sender, RoutedEventArgs e) { FrameworkElement sourceFrameworkElement = e.Source as FrameworkElement; switch (sourceFrameworkElement.Name) { case "YesButton": // YesButton logic. break; case "NoButton": // NoButton logic. break; case "CancelButton": // CancelButton logic. break; } e.Handled = true; }
Private Sub YesNoCancelButton_Click(sender As Object, e As RoutedEventArgs) Dim frameworkElementSource As FrameworkElement = TryCast(e.Source, FrameworkElement) Select Case frameworkElementSource.Name Case "YesButton" ' YesButton logic. Case "NoButton" ' NoButton logic. Case "CancelButton" ' CancelButton logic. End Select e.Handled = True End Sub
類別處理:路由事件支援您在類別中定義的類別事件處理常式。 類別處理常式會在類別的任何執行個體上處理相同事件的任何執行個體處理常式之前處理事件。
在沒有反映的情況下參考事件:每個路由事件都會建立 RoutedEvent (英文) 欄位識別碼,以提供不需要靜態或執行階段反映來識別事件的強固事件識別技術。
路由事件的實作方式
路由事件是向 WPF 事件系統註冊的事件,由 RoutedEvent (英文) 類別的執行個體所支援,並由 WPF 事件系統處理。 從RoutedEvent
(英文) 取得的 執行個體通常會儲存為註冊它之類別的 public static readonly
成員。 該類別稱為事件「擁有者」類別。 路由事件通常會實作同名 CLR 事件「包裝函式」。 CLR 事件包裝函式包含 add
和 remove
存取子,可透過語言專有事件語法在 XAML 和程式碼後置中啟用附加處理常式。
add
和 remove
存取子會覆寫其 CLR 實作,並呼叫路由事件 AddHandler (部分機器翻譯) 和 RemoveHandler (英文) 方法。 路由事件支援和連線機制在概念上類似於相依性屬性是 CLR 屬性的方式,該屬性是由 DependencyProperty 類別所支援,並向 WPF 屬性系統註冊。
下列範例會註冊 Tap
路由事件、儲存傳回的 RoutedEvent
執行個體,並實作 CLR 事件包裝函式。
// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
name: "Tap",
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(CustomButton));
// Provide CLR accessors for adding and removing an event handler.
public event RoutedEventHandler Tap
{
add { AddHandler(TapEvent, value); }
remove { RemoveHandler(TapEvent, value); }
}
' Register a custom routed event using the Bubble routing strategy.
Public Shared ReadOnly TapEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
name:="Tap",
routingStrategy:=RoutingStrategy.Bubble,
handlerType:=GetType(RoutedEventHandler),
ownerType:=GetType(CustomButton))
' Provide CLR accessors for adding and removing an event handler.
Public Custom Event Tap As RoutedEventHandler
AddHandler(value As RoutedEventHandler)
[AddHandler](TapEvent, value)
End AddHandler
RemoveHandler(value As RoutedEventHandler)
[RemoveHandler](TapEvent, value)
End RemoveHandler
RaiseEvent(sender As Object, e As RoutedEventArgs)
[RaiseEvent](e)
End RaiseEvent
End Event
路由傳送策略
路由事件會使用下列其中一個路由傳送策略:
事件反昇 (英文):一開始,會叫用事件來源上的事件處理常式。 路由事件接著會路由傳送至後續父元素,進而接著叫用其事件處理常式,直到到達元素樹狀結構根目錄為止。 大部分的路由事件會使用事件反昇路由傳送策略。 事件反昇的路由事件通常是用來報告來自複合控制項或其他 UI 元素的輸入或狀態變更。
通道︰一開始會叫用元素樹狀結構根元素上的事件處理常式。 路由事件接著會路由傳送至後續子元素,進而接著叫用其事件處理常式,直到到達事件來源為止。 遵循通道路由的事件也稱為預覽事件。 WPF 輸入事件通常會實作為預覽和事件反昇配對。
直接 (英文):只會叫用事件來源上的事件處理常式。 此非路由策略類似於 Windows Forms UI 架構事件,也就是標準 CLR 事件。 不同於 CLR 事件,直接路由事件支援類別處理 (部分機器翻譯),而且可由 EventSetters (部分機器翻譯) 和 EventTriggers (部分機器翻譯) 使用。
為什麼要使用路由事件?
身為應用程式開發人員,您不一定需要知道或在意您正在處理的事件是否已實作為路由事件。 路由事件有特殊的行為,但是,如果您正在引發事件的元素上處理事件,則大多不會看見該行為。 不過,當您想要將事件處理常式附加至父元素,以處理子元素所引發的事件時 (例如在複合控制項內),路由事件是相關的。
路由事件接聽程式不需要其處理的路由事件為其類別的成員。 任何 UIElement 或 ContentElement 可以是任何路由事件的事件接聽程式。 由於視覺元素衍生自 UIElement
或 ContentElement
,因此您可以使用路由事件作為概念性的「介面」,以支援在應用程式中的不同元素之間交換事件資訊。 路由事件的「介面」概念特別適用於輸入事件 (部分機器翻譯)。
路由事件支援在事件路由上的元素之間交換事件資訊,因為每個接聽程式都能夠存取相同的事件資料執行個體。 如果某個元素在事件資料中變更某個項目,事件路由中的後續元素就會看到該變更。
除了路由層面之外,您可以選擇實作路由事件,而不是標準 CLR 事件,原因如下:
某些 WPF 樣式和範本化功能 (例如 EventSetters (部分機器翻譯) 和 EventTriggers (部分機器翻譯)) 要求參考的事件必須是路由事件。
路由事件支援類別事件處理常式,其會在接聽程式類別的任何實執行個體上處理相同事件的任何實例處理程式之前處理事件。 此功能在控制項設計中非常有用,因為您的類別處理常式可以強制執行事件驅動的類別行為,這些行為無法由執行個體處理常式意外隱藏。
附加並實作路由事件處理常式
在 XAML 中,您可以透過將事件名稱宣告為事件接聽程式元素上的屬性,以將事件處理常式附加至元素。 屬性值是您的處理常式方法名稱。 處理常式方法必須在 XAML 頁面的程式碼後置部分類別中實作。 事件接聽程式是附加和叫用事件處理常式所在的元素。
針對屬於接聽程式類別成員 (繼承或其他) 的事件,您可以附加處理常式,如下所示:
<Button Name="Button1" Click="Button_Click">Click me</Button>
如果事件不是接聽程式類別的成員,您必須以 <owner type>.<event name>
的形式使用限定的事件名稱。 例如,由於 StackPanel 類別不會實作 Click 事件,因此若要將處理常式附加至反昇至該元素之 StackPanel
事件的 Click
,您必須使用限定的事件名稱語法:
<StackPanel Name="StackPanel1" Button.Click="Button_Click">
<Button>Click me</Button>
</StackPanel>
程式碼後置中事件處理常式方法的簽章必須符合路由事件的委派類型。
sender
事件之 RoutedEventHandler 委派的 Click 參數會指定要附加事件處理常式的元素。
args
委派的 RoutedEventHandler
參數包含事件資料。
Button_Click
事件處理常式的相容程式碼後置實作可能是:
private void Button_Click(object sender, RoutedEventArgs e)
{
// Click event logic.
}
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
' Click event logic.
End Sub
雖然 RoutedEventHandler 是基本的路由事件處理常式委派,但某些控制項或實作案例需要支援更特殊化事件資料的不同委派。 例如,針對 DragEnter (部分機器翻譯) 路由事件,您的處理常式應該實作 DragEventHandler (部分機器翻譯) 委派。 如此一來,處理常式程式碼就可以存取事件資料 (其中包含拖曳作業中的剪貼簿承載) 中的 DragEventArgs.Data 屬性。
用於新增路由事件處理常式的 XAML 語法與標準 CLR 事件處理常式相同。 如需在 XAML 中新增事件處理程式的詳細資訊,請參閱在 WPF 中 XAML。 如需如何使用 XAML 將事件處理常式附加至元素的完整範例,請參閱如何處理路由事件。
若要使用程式碼將路由事件的事件處理常式附加至元素,您通常有兩個選項:
直接呼叫 AddHandler (部分機器翻譯) 方法。 路由事件處理常式一律能以此方式附加。 此範例會使用
Click
方法,將AddHandler
事件處理常式附加至按鈕:Button1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click));
Button1.[AddHandler](ButtonBase.ClickEvent, New RoutedEventHandler(AddressOf Button_Click))
若要將按鈕的
Click
事件的處理常式附加至事件路由中的不同元素,例如名為 StackPanel 的StackPanel1
:StackPanel1.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(Button_Click));
StackPanel1.[AddHandler](ButtonBase.ClickEvent, New RoutedEventHandler(AddressOf Button_Click))
如果路由事件實作 CLR 事件包裝函式,請使用語言專有的事件語法來新增事件處理常式,就像針對標準 CLR 事件一樣。 大部分現有的 WPF 路由事件都會實作 CLR 包裝函式,從而啟用語言專有的事件語法。 此範例會使用語言專有語法,將
Click
事件處理常式附加至按鈕:Button1.Click += Button_Click;
AddHandler Button1.Click, AddressOf Button_Click
如需如何在程式碼中附加事件處理常式的範例,請參閱如何使用程式碼新增事件處理常式。 如果您使用 Visual Basic 撰寫程式碼,您也可以使用 Handles
關鍵字,將處理常式新增為處理常式宣告的一部分。 如需詳細資訊,請參閱 Visual Basic 和 WPF 事件處理。
handled 的概念
所有路由事件都會共用事件資料的基底類別,也就是 RoutedEventArgs (部分機器翻譯) 類別。
RoutedEventArgs
類別會定義布林值 Handled (部分機器翻譯) 屬性。
Handled
屬性的目的是讓事件路由上的任何事件處理常式將路由事件標示為「已處理」。 若要將事件標示為已處理,請在事件處理常式程式碼中將 Handled
的值設定為 true
。
Handled
的值會影響路由事件在沿著事件路由移動時的處理方式。 在路由事件的共用事件資料中,若 Handled
為 true
,則附加至沿著事件路由之其他元素的處理常式通常不會針對該特定事件執行個體叫用。 針對最常見的處理常式案例,將事件標示為已處理會有效地讓沿著事件路由的後續處理常式 (無論是執行個體或類別處理常式) 停止回應該特定事件執行個體。 不過,在需要事件處理常式回應已標示為已處理之路由事件的罕見情況下,您可以:
使用 AddHandler(RoutedEvent, Delegate, Boolean) (部分機器翻譯) 多載在程式碼後置中附加處理常式,並將
handledEventsToo
參數設定為true
。將 HandledEventsToo(英文) 屬性設定為
EventSetter
或true
。
Handled
的概念可能會影響您設計應用程式和撰寫事件處理常式程式碼的方式。 您可以將 Handled
概念化為處理路由事件的簡單通訊協定。 使用此通訊協定的方式由您決定,但預期的 Handled
參數用法如下:
如果將路由事件標示為已處理,則不需再次透過沿著該路由的其他元素來處理它。
如果未將路由事件標示為已處理,則事件路由中稍早的接聽程式沒有事件的處理常式,或沒有任何已註冊的處理常式回應事件,以讓事件標示為已處理。 目前接聽程式上的處理常式有三個可能的行動步驟:
不採取任何動作。 事件會保持未處理狀態,而且會路由傳送至樹狀結構中的下一個接聽程式。
執行程式碼以回應事件,但不會將事件標示為已處理。 事件會保持未處理狀態,而且會路由傳送至樹狀結構中的下一個接聽程式。
執行程式碼以回應事件,將事件標示為已處理。 在事件資料中將事件標示為已處理。 事件仍會路由傳送至樹狀結構中的下一個接聽程式,但大部分接聽程式不會叫用進一步的處理常式。 例外狀況是具有已特別向設定為
handledEventsToo
的true
註冊之處理常式的接聽程式。
如需有關處理路由事件的詳細資訊,請參閱將路由事件標記為已處理以及類別處理。
雖然只處理引發之物件上事件反昇之路由事件的開發人員可能不關心其他接聽程式,但最好還是將事件標示為已處理。 如果進一步沿著事件路由上的元素有相同路由事件的處理常式,則這樣做可防止非預期的副作用。
類別處理常式
路由事件處理常式可以是實例處理常式或類別處理常式。 指定類別的類別處理常式,會在任何實例處理常式對該類別任何實例上的相同事件做出回應之前叫用。 由於此行為,當路由事件標示為已處理時,其通常也會在類別處理常式中標示為已處理。 類別處理常式有兩種類型:
- 靜態類別事件處理常式,其註冊方式為在靜態類別建構函式內呼叫 RegisterClassHandler 方法。
- 覆寫類別事件處理常式,其註冊方式為覆寫基底類別虛擬事件方法。 基底類別虛擬事件方法主要存在於輸入事件中,且名稱開頭為 On<event name> 以及 OnPreview<event name>。
某些 WPF 控制項具有特定路由事件的固有類別處理。 類別處理可能會提供路由事件從未引發的外表,但實際上,它被標示為由類別處理常式處理。 如果需要事件處理常式回應已處理的事件,您可以向設定為 handledEventsToo
的 true
註冊處理常式。 如需有關實作自己的類別處理常式或因應不想要的類別處理的詳細資訊,請參閱將路由事件標記為已處理以及類別處理。
在 WPF 中附加事件
XAML 語言也定義為特殊事件,稱為 附加事件 。 附加事件可用來在非元素類別中定義新的路由事件,並在樹狀結構中的任何元素上引發該事件。 若要這樣做,您必須將附加事件註冊為路由事件,並提供支援附加事件功能的特定支援程式碼。 由於附加事件註冊為路由事件,因此在元素上引發時,會透過元素樹狀結構散佈。
在 XAML 語法中,附加事件是由其事件名稱和擁有者類型所指定,格式為 <owner type>.<event name>
。 因為事件名稱限定為其擁有者類型的名稱,因此語法可讓事件附加至可具現化的任何元素。 對於附加至事件路由中任意元素的一般路由事件,此語法也適用於其處理常式。 您也可以在處理常式應該附加至的物件上呼叫 AddHandler 方法,在程式碼後置中針對附加事件附加處理常式。
WPF 輸入系統會廣泛使用附加事件。 不過,幾乎所有附加事件都會透過基礎元素呈現為相等的非附加路由事件。 您很少會直接使用或處理附加事件。 例如,透過相等的 Mouse.MouseDown 路由事件在 UIElement 上處理基礎附加 UIElement.MouseDown 事件,比在 XAML 或程式碼後置中使用附加事件語法更為容易。
如需 WPF 中附加事件的詳細資訊,請參閱附加事件概觀。
XAML 中的完整事件名稱
<owner type>.<event name>
語法會使用其擁有者類型的名稱來限定事件名稱。 此語法可讓事件附加至任何元素,而不只是將事件實作為其類別成員的元素。 針對沿著事件路由任意元素上的附加事件或路由事件在 XAML 中附加處理常式時,適用該語法。 請考慮您想要將處理常式附加至父元素,以處理子元素上引發的路由事件的案例。 如果父元素沒有路由事件做為成員,您必須使用限定的事件名稱語法。 例如:
<StackPanel Name="StackPanel1" Button.Click="Button_Click">
<Button>Click me</Button>
</StackPanel>
在範例中,在其中新增事件處理常式的父元素接聽程式是 StackPanel (部分機器翻譯)。 不過,Click (部分機器翻譯) 路由事件會在 ButtonBase (部分機器翻譯) 類別上實作和引發,並透過繼承提供給 Button (部分機器翻譯) 類別。 雖然 Button (部分機器翻譯) 類別「擁有」Click
事件,但路由事件系統允許任何路由事件的處理常式附加至任何 UIElement (部分機器翻譯) 或 ContentElement (部分機器翻譯) 執行個體接聽程式,否則這些接聽程式會有 CLR 事件的接聽程式。 這些限定事件屬性名稱的預設 xmlns
命名空間通常是預設的 WPF xmlns
命名空間,但您也可以為自訂路由事件指定前置命名空間。 如需 xmlns
的詳細資訊,請參閱 WPF XAML 的 XAML 命名空間和命名空間對應。
WPF 輸入事件
WPF 平台內路由事件的一個常見應用是輸入事件 (部分機器翻譯)。 依照慣例,遵循通道路由的 WPF 路由事件具有前面加上「Preview」的名稱。 「Preview」字首表示預覽事件會在配對的事件反昇事件開始之前完成。 輸入事件通常會成對出現,其中一個是預覽事件,而另一個則是事件反昇路由事件。 例如,PreviewKeyDown 與 KeyDown。 事件配對會共用相同的事件資料執行個體,這是針對 PreviewKeyDown
和 KeyDown
為 KeyEventArgs (部分機器翻譯) 類型。 有時,輸入事件只會有事件反昇版本,或只有直接路由版本。 在 API 文件中,路由事件主題會交叉參考路由事件配對,並釐清每個路由事件的路由策略。
會實作成對的 WPF 輸入事件,以便輸入裝置中的單一使用者動作 (例如按下滑鼠按鍵) 將會依序引發預覽和事件反昇路由事件。 首先,會引發預覽事件並完成其路由。 在預覽事件完成時,會引發事件反昇事件並完成其路由。 實作類別中引發事件反昇事件的 RaiseEvent (英文) 方法呼叫會針對事件反昇事件重複使用來自預覽事件的事件資料。
標示為已處理的預覽輸入事件不會針對預覽路由的其餘部分叫用任何以正常方式註冊的事件處理常式,而且不會引發配對的事件反昇事件。 此處理行為適用於下列複合控制項設計人員:想要在其控制項的最上層報告點擊測試型輸入事件或以焦點為基礎的輸入事件。 控制項的最上層元素有機會從控制項子元件對預覽事件進行類別處理,以便以最上層控制項專有事件來「取代」它們。
如需輸入事件處理如何運作的圖表說明,請考慮下列輸入事件範例。 在下列樹狀結構圖中,leaf element #2
是 PreviewMouseDown
和 MouseDown
配對事件的來源:
在分葉元素 #2 上執行滑鼠按下動作之後的事件處理順序為:
- 根元素上的
PreviewMouseDown
通道事件。 - 中繼元素 #1 上的
PreviewMouseDown
通道事件。 - 分葉元素 #2 上的
PreviewMouseDown
通道事件,也就是來源元素。 - 分葉元素 #2 上的
MouseDown
事件反昇事件,也就是來源元素。 - 中繼元素 #1 上的
MouseDown
事件反昇事件。 - 根元素上的
MouseDown
事件反昇事件。
路由事件處理常式委派提供對兩個物件的參考︰引發事件的物件,以及已叫用處理常式的物件。 事件第一次引發的物件是由事件資料中的 Source (英文) 屬性所報告。 已叫用處理常式的物件是由 sender (部分機器翻譯) 參數所報告。 針對任何指定的路由事件執行個體,引發事件的物件不會隨著事件在元素樹狀結構中移動而變更,但 sender
會。 在上圖的步驟 3 和 4 中,Source
和 sender
是相同的物件。
如果您的輸入事件處理常式完成處理事件所需的應用程式專有邏輯,您應該將輸入事件標示為已處理。 一般而言,一旦將輸入事件標示為 Handled (部分機器翻譯),就不會叫用沿著事件路由的進一步處理常式。 不過,即使事件標示為已處理,也會叫用已向設定為 handledEventsToo
之 true
參數註冊的輸入事件處理常式。 如需詳細資訊,請參閱預覽事件和將路由事件標記為已處理以及類別處理。
預覽和事件反昇事件配對的概念,其中共用事件資料和循序引發預覽事件,然後引發事件反昇事件,僅適用於某些 WPF 輸入事件,不適用於所有路由事件。 如果您實作自己的輸入事件來解決進階案例,請考慮遵循 WPF 輸入事件配對方法。
如果您要實作自己的複合控制項來回應輸入事件,請考慮使用預覽事件來隱藏子元件上引發的輸入事件,並取代為代表完整控制項的最上層事件。 如需詳細資訊,請參閱將路由事件標記為已處理以及類別處理。
如需 WPF 輸入系統以及一般應用程式案例中輸入如何與事件互動的詳細資訊,請參閱輸入概觀 (部分機器翻譯)。
EventSetters 和 EventTriggers
在標記樣式中,您可以使用 EventSetter (部分機器翻譯) 來包含一些預先宣告的 XAML 事件處理語法。 處理 XAML 時,會將參考的處理常式新增至樣式執行個體。 您只能針對路由事件宣告 EventSetter
。 在下列範例中,參考的 ApplyButtonStyle
事件處理常式方法會在程式碼後置中實作。
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<EventSetter Event="Click" Handler="ApplyButtonStyle"/>
</Style>
</StackPanel.Resources>
<Button>Click me</Button>
<Button Click="Button_Click">Click me</Button>
</StackPanel>
Style
節點可能已經包含與指定類型控制項相關的其他樣式資訊,而且讓 EventSetter (部分機器翻譯) 成為那些樣式的一部分可促進程式碼重複使用 (即使是在標記層級)。 此外,EventSetter
會將處理常式的方法名稱從一般應用程式和頁面標記抽象化。
另一個結合 WPF 路由事件和動畫功能的特殊語法是 EventTrigger。 使用 EventSetter
時,您只能針對路由事件宣告 EventTrigger
。 一般而言,EventTrigger
會宣告為樣式的一部分,但 EventTrigger
可在頁面層級元素上宣告為 Triggers (部分機器翻譯) 集合的一部分,或在 ControlTemplate (部分機器翻譯) 中宣告。
EventTrigger
可讓您指定每當路由事件到達其路由中宣告該事件的 Storyboard 時,就會執行 EventTrigger
。
EventTrigger
不只是處理事件,並導致它啟動現有的分鏡腳本的優點是, EventTrigger
提供對分鏡腳本及其運行時間行為的更佳控制。 如需詳細資訊,請參閱在分鏡腳本開始後使用事件觸發程序進行控制 (部分機器翻譯)。
深入了解路由事件
當在您自己的類別中建立自訂路由事件時,可以使用本文中的概念和指引作為起點。 您也可以使用特殊化事件資料類別和委派來支援自訂事件。 路由事件擁有者可以是任何類別,但路由事件必須由 UIElement (部分機器翻譯) 或 ContentElement (部分機器翻譯) 衍生類別引發及處理,才能有用。 如需自訂事件的詳細資訊,請參閱建立自訂路由事件。