路由事件概觀

本主題說明 Windows Presentation Foundation (WPF) 中路由事件的概念。 本主題會定義路由事件的術語、說明如何透過元素的樹狀結構路由傳送路由事件、摘要說明如何處理路由事件,以及介紹如何建立您自己的自訂路由事件。

必要條件

本主題假設您有 common language runtime (CLR) 和麵向物件程式設計的基本知識,以及如何將元素之間的關聯性概念 WPF 化為樹狀結構。 若要遵循本主題中的範例,您也應該了解 Extensible Application Markup Language (XAML),並知道如何撰寫非常基本的 WPF 應用程式或頁面。 如需詳細資訊,請參閱 逐步解說:我的第一個 wpf 桌面應用程式Wpf 中的 XAML

什麼是路由事件?

您可以從功能或實作觀點來考量路由事件。 此處說明這兩個定義,讓使用者能夠選擇較實用的定義。

功能定義︰路由事件是一種事件類型,可在元素樹狀結構中的多個接聽程式上叫用處理常式,而不只是在引發事件的物件上。

實作為定義:路由事件是由類別的實例所支援的 CLR 事件, RoutedEvent 由 Windows Presentation Foundation (WPF) 事件系統處理。

一般的 WPF 應用程式包含許多元素。 不論是在程式碼中建立或是在 XAML 中宣告,這些元素均存在於彼此間的元素樹狀結構關聯性中。 事件路由的周遊方向取決於事件定義,但通常路由會從來源元素開始周遊,然後透過元素樹狀結構向上執行「事件反昇」,直到它到達元素樹狀結構根元素 (通常是頁面或視窗) 為止。 如果您先前曾用過 DHTML 物件模型,可能很熟悉這個事件反昇概念。

請考慮下列簡單的元素樹狀結構:

<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1">
  <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">
    <Button Name="YesButton" Width="Auto" >Yes</Button>
    <Button Name="NoButton" Width="Auto" >No</Button>
    <Button Name="CancelButton" Width="Auto" >Cancel</Button>
  </StackPanel>
</Border>

這個元素樹狀結構會產生如下的畫面:

是、否和取消按鈕

在這個簡化的元素樹狀結構中, Click 事件來源是其中一個 Button 元素,而按下的 Button 是第一個有機會處理事件的專案。 但是,如果沒有附加至事件的處理常式 Button ,則事件會向上反升至專案 Button 樹狀結構中的父代,也就是 StackPanel 。 事件可能會反升至專案 Border 樹狀結構的頁面根 (,但不會顯示) 。

換句話說,此事件的事件路由 Click 為:

Button-->StackPanel-->Border-->...

路由事件的最上層案例

以下是促使路由事件概念的案例的簡短摘要,以及為什麼一般 CLR 事件不適合這些案例:

控制項組合和封裝︰WPF 中的各種控制項具有豐富的內容模型。 例如,您可以將影像放在中,以 Button 有效擴充按鈕的視覺化樹狀結構。 但是,新增的映射不能中斷造成按鈕回應其內容的點擊測試行為 Click ,即使使用者按一下的圖元是影像中技術上的一部分也一樣。

單一處理程式附件點: 在 Windows Forms 中,您必須多次附加相同的處理常式,以處理可從多個元素引發的事件。 路由事件可讓您只需附加該處理常式一次 (如上一個範例中所示),然後就能視需要使用處理常式邏輯判斷此事件來自何處。 例如,這可能是先前所示之 XAML 的處理常式:

private void CommonClickHandler(object sender, RoutedEventArgs e)
{
  FrameworkElement feSource = e.Source as FrameworkElement;
  switch (feSource.Name)
  {
    case "YesButton":
      // do something here ...
      break;
    case "NoButton":
      // do something ...
      break;
    case "CancelButton":
      // do something ...
      break;
  }
  e.Handled=true;
}
Private Sub CommonClickHandler(ByVal sender As Object, ByVal e As RoutedEventArgs)
  Dim feSource As FrameworkElement = TryCast(e.Source, FrameworkElement)
  Select Case feSource.Name
    Case "YesButton"
      ' do something here ...
    Case "NoButton"
      ' do something ...
    Case "CancelButton"
      ' do something ...
  End Select
  e.Handled=True
End Sub

類別處理: 路由事件允許類別所定義的靜態處理常式。 這個類別處理常式有機會在任何附加的執行個體處理常式之前處理事件。

參考事件,但不使用反射: 特定程式碼和標記技術需要識別特定事件的方式。 路由事件 RoutedEvent 會將欄位建立為識別碼,以提供不需要靜態或執行時間反映的健全事件識別技術。

路由事件的實作方式

路由事件是由類別的實例所支援 RoutedEvent 並向事件系統註冊的 CLR 事件 WPF 。 RoutedEvent從註冊取得的實例通常會保留為 public static readonly 註冊之類別的欄位成員,因此「擁有」路由事件。 與相同命名 CLR 事件 (的連接,有時也稱為「包裝函式」事件) 是藉由覆寫 add CLR 事件的和執行來完成 remove 。 一般而言,addremove 會保留為隱含的預設值,以使用適當的語言特定事件語法來加入和移除該事件的處理常式。 路由事件支援和連接機制在概念上類似于相依性屬性是由 DependencyProperty 類別支援並向屬性系統註冊的 CLR 屬性 WPF 。

下列範例顯示自訂路由事件的宣告 Tap ,包括註冊和公開 RoutedEvent CLR 事件的識別碼欄位和 addremoveTap

public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
    "Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));

// Provide CLR accessors for the event
public event RoutedEventHandler Tap
{
        add { AddHandler(TapEvent, value); }
        remove { RemoveHandler(TapEvent, value); }
}
Public Shared ReadOnly TapEvent As RoutedEvent = EventManager.RegisterRoutedEvent("Tap", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(MyButtonSimple))

' Provide CLR accessors for the event
Public Custom Event Tap As RoutedEventHandler
    AddHandler(ByVal value As RoutedEventHandler)
        Me.AddHandler(TapEvent, value)
    End AddHandler

    RemoveHandler(ByVal value As RoutedEventHandler)
        Me.RemoveHandler(TapEvent, value)
    End RemoveHandler

    RaiseEvent(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Me.RaiseEvent(e)
    End RaiseEvent
End Event

路由事件處理常式和 XAML

若要使用 XAML 加入事件的處理常式,您可以宣告事件名稱做為屬於事件接聽程式之元素上的屬性。 屬性的值是您所實作之處理常式方法的名稱,此名稱必須存在於程式碼後置檔案的部分類別中。

<Button Click="b1SetColor">button</Button>

加入 XAML 標準 CLR 事件處理常式的語法與加入路由事件處理常式相同,因為您實際上是將處理常式加入至 CLR 事件包裝函式,而該包裝函式下有路由事件的執行。 如需在中新增事件處理常式的詳細資訊 XAML ,請參閱 WPF 中的 XAML

路由傳送策略

路由事件會使用下列其中一個路由傳送策略:

  • 事件反昇︰ 會叫用事件來源上的事件處理常式。 路由事件接著會路由傳送到後續的父元素,直到其到達元素樹狀結構的根元素為止。 大部分的路由事件會使用事件反昇路由傳送策略。 事件反昇的路由事件通常是用來報告來自不同控制項或其他 UI 元素的輸入或狀態變更。

  • 直接︰ 只有來源元素本身有機會叫用處理常式來回應。 這類似于 Windows Forms 用於事件的「路由」。 不過,不同于標準 CLR 事件,直接路由事件支援類別處理 (類別處理會在下一節中說明) 並且可供 EventSetter 和使用 EventTrigger

  • 通道︰ 一開始會叫用元素樹狀結構根元素上的事件處理常式。 路由事件接著會在路由中朝向屬於路由事件來源的節點元素 (會引發路由事件的元素) 移動,以透過後續的子元素周遊該路由。 通道路由事件時常會做為複合控制項的一部分來使用或處理,這類來自複合組件的事件可利用專用於該完整控制項的事件來刻意隱藏或取代。 WPF 中提供的輸入事件通常會實作為成對的通道/事件反昇組合。 由於用於配對的命名慣例,通道事件有時也稱為預覽事件。

為什麼要使用路由事件?

身為應用程式開發人員,您不一定需要知道或在意要將您正在處理的事件實作為路由事件。 路由事件都有特殊的行為,但是,如果您正在引發事件的元素上處理該事件,則大多不會看見該行為。

路由事件變成功能強大之處在於,您是否使用任何建議的案例︰在一般的根元素上定義一般的處理常式、組合自己的控制項,或定義自己的控制項類別。

路由事件接聽程式和路由事件來源不需要在其階層中共用一般事件。 任何 UIElementContentElement 可以是任何路由事件的事件接聽程式。 因此,您可以在整個工作 API 集內使用一組完整的路由事件,作為概念「介面」,讓應用程式中的不同元素可以交換事件資訊。 路由事件的這個「介面」概念特別適用於輸入事件。

路由事件也可用來透過元素樹狀結構進行通訊,因為事件的事件資料會永久存在於路由的每個元素中。 一個元素可以變更事件資料中的某些內容,而該變更可供路由中的下一個元素使用。

除了路由層面以外,還有其他兩個原因:任何指定的 WPF 事件可能會實作為路由事件,而非標準 CLR 事件。 如果您要實作自己的事件,也可以考慮這些準則:

  • 某些 WPF 樣式設定和範本化功能(例如 EventSetter 和) EventTrigger 要求參考的事件必須是路由事件。 這是先前所述的事件識別碼案例。

  • 路由事件支援類別處理機制,此類別可藉以指定靜態方法,有機會在任何已註冊的執行個體處理常式可存取路由事件之前處理它們。 這在控制項設計中非常有用,因為您的類別可以強制執行事件驅動的類別行為,您無法藉由處理執行個體上的事件來附帶隱藏這類行為。

上述每個考量都會在本主題的不同小節中加以討論。

加入和實作路由事件的事件處理常式

若要在 XAML 中加入事件處理常式,您只需將事件名稱加入至元素做為屬性,並將屬性值設為實作適當委派的事件處理常式名稱,如下列範例所示。

<Button Click="b1SetColor">button</Button>

b1SetColor 這是所執行的處理常式名稱,其中包含處理事件的程式碼 Clickb1SetColor 必須具有與委派相同的簽章 RoutedEventHandler ,也就是事件的事件處理常式委派 Click 。 所有路由事件處理常式委派的第一個參數會指定要加入事件處理常式的元素,而第二個參數會指定事件的資料。

void b1SetColor(object sender, RoutedEventArgs args)
{
  //logic to handle the Click event
}
Private Sub b1SetColor(ByVal sender As Object, ByVal args As RoutedEventArgs)
  'logic to handle the Click event
End Sub

RoutedEventHandler 這是基本的路由事件處理常式委派。 如果是針對特定控制項或案例特製化的路由事件,用於路由事件處理常式的委派也可能會變得更特製化,讓它們能夠傳輸特製化的事件資料。 例如,在一般輸入案例中,您可能會處理 DragEnter 路由事件。 您的處理常式應該會執行 DragEventHandler 委派。 您可以使用最特定的委派來處理 DragEventArgs 處理常式中的,並讀取 Data 屬性,其中包含拖曳作業的剪貼簿承載。

如需如何使用 XAML 來將事件處理常式加入至元素的完整範例,請參閱處理路由事件

在使用程式碼建立的應用程式中加入路由事件的處理常式很簡單。 路由事件處理常式一律可以透過 helper 方法加入 AddHandler (這與現有的支援呼叫的方法相同 add ) 。不過,現有的 WPF 路由事件通常具有的支援 add 和邏輯,可 remove 讓路由事件的處理常式透過特定語言的事件語法來新增,這比協助程式方法更直覺。 以下是 Helper 方法的使用方式範例:

void MakeButton()
 {
     Button b2 = new Button();
     b2.AddHandler(Button.ClickEvent, new RoutedEventHandler(Onb2Click));
 }
 void Onb2Click(object sender, RoutedEventArgs e)
 {
     //logic to handle the Click event
 }
Private Sub MakeButton()
     Dim b2 As New Button()
     b2.AddHandler(Button.ClickEvent, New RoutedEventHandler(AddressOf Onb2Click))
End Sub
 Private Sub Onb2Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
     'logic to handle the Click event     
 End Sub

下一個範例顯示 c # 運算子語法 (Visual Basic 有稍微不同的運算子語法,因為它的取值) :

void MakeButton2()
{
  Button b2 = new Button();
  b2.Click += new RoutedEventHandler(Onb2Click2);
}
void Onb2Click2(object sender, RoutedEventArgs e)
{
  //logic to handle the Click event
}
Private Sub MakeButton2()
  Dim b2 As New Button()
  AddHandler b2.Click, AddressOf Onb2Click2
End Sub
Private Sub Onb2Click2(ByVal sender As Object, ByVal e As RoutedEventArgs)
  'logic to handle the Click event     
End Sub

如需如何在程式碼中加入事件處理常式的範例,請參閱使用程式碼加入事件處理常式

如果您使用 Visual Basic,也可以使用 Handles 關鍵字,將處理常式新增為處理常式宣告的一部分。 如需詳細資訊,請參閱 Visual Basic 和 WPF 事件處理

已處理的概念

所有路由事件都共用一個通用的事件資料基類 RoutedEventArgsRoutedEventArgs 定義 Handled 接受布林值的屬性。 屬性的用途是將的 Handled 值設定為,以便在路由上啟用任何事件處理常式, 以將路由事件標示為已 Handled 處理 true 。 透過處理常式在路由中的某一個元素上進行處理之後,就會再次向路由中的每一個接聽程式報告共用的事件資料。

的值 Handled 會影響路由事件的報告或處理方式,因為路由事件會沿著路由往上移動。 如果 Handled 位於 true 路由事件的事件資料中,則在其他元素上接聽該路由事件的處理常式通常不會再針對該特定事件實例叫用。 此情況適用於 XAML 中附加的處理常式,以及適用於利用語言特定之事件處理常式附加語法 (例如 +=Handles) 所加入的處理常式。 針對大部分常見的處理常式案例,將事件標示為已處理, Handled 會將設定為「 true 停止」路由傳送通道路由或反升路由,而且也適用于在路由中由類別處理常式點處理的任何事件。

不過,有一個「handledEventsToo」機制,因此接聽程式仍然可以執行處理常式來回應 Handled true 事件資料中的路由事件。 換句話說,事件路由無法藉由將事件資料標示為已處理來真正停止。 您只能在程式碼或中使用 handledEventsToo 機制 EventSetter

除了 Handled 狀態在路由事件中產生的行為之外,的概念 Handled 也會影響您應該如何設計應用程式並撰寫事件處理常式程式碼。 您可以將概念概念化 Handled 為路由事件所公開的簡單通訊協定。 您使用此通訊協定的確切方式是由您決定,但是要如何使用其值的概念設計如下 Handled

  • 如果將路由事件標示為已處理,則不需再次透過該路由中的其他元素來處理它。

  • 如果路由事件未標示為已處理,則先前在路由中的其他接聽程式已選擇不註冊處理常式,或已註冊的處理常式選擇不操作事件資料並設定 Handledtrue 。 (或者,目前的接聽程式當然可能是路由中的第一個點。目前接聽程式上的 ) 處理常式現在有三個可能的動作課程:

    • 不採取任何動作;事件會保持未處理狀態,而事件會路由傳送到下一個接聽程式。

    • 執行程式碼以回應事件,但判定採取的動作後續不足以保證會將事件標示為已處理。 事件會路由傳送到下一個接聽程式。

    • 執行程式碼以回應事件。 在傳遞至處理常式的事件資料中將事件標示為已處理,因為已將所採取的動作視為後續不足以保證會標示為已處理。 事件仍會路由傳送至下一個接聽程式,但 Handled = true 在其事件資料中,因此只有接聽 handledEventsToo 程式有機會叫用進一步的處理常式。

這個概念設計是由稍早所述的路由行為來加強:雖然在程式碼或樣式中仍能附加處理常式(即使路由的上一個處理常式已設定為),但在程式碼或) 樣式中仍能附加處理常式,也是很困難的 (Handled true

Handled 需有關路由事件的類別處理,以及將路由事件標示為適當時機的建議, Handled 請參閱將 路由事件標示為已處理以及類別處理

在應用程式中,只在引發事件反昇路由事件的物件上處理該事件是相當常見的,而這並不完全與事件的路由特性有關。 不過,它仍是在事件資料中將路由事件標示為已處理的最佳做法,萬一元素樹狀結構中進一步向上的元素也具有已針對該相同路由事件附加的處理常式時,可避免發生未預期的副作用。

類別處理常式

如果您要定義以某種方式衍生的類別 DependencyObject ,您也可以定義和附加屬於您類別之已宣告或繼承事件成員之路由事件的類別處理常式。 每當路由事件到達其路由中的元素執行個體時,就可以在任何附加至該類別執行個體的執行個體接聽程式處理常式之前叫用類別處理常式。

某些 WPF 控制項具有適用於特定路由事件的繼承類別處理。 這可能會造成表面上未曾引發過路由事件,但實際上卻已處理過類別的情況,而且,如果您使用某些技術,您的執行個體處理常式可能仍會處理該路由事件。 此外,許多基底類別和控制項會公開可用於覆寫類別處理行為的虛擬方法。 如需如何因應不想要的類別處理,並在自訂類別中定義您自己之類別處理的詳細資訊,請參閱將路由事件標記為已處理以及類別處理

在 WPF 中附加事件

XAML 語言也會定義稱為「附加事件」的特定事件類型。 附加事件可讓您將特殊事件的處理常式加入至任意元素。 處理事件的元素不需要定義或繼承附加事件,而物件不可能引發事件,且目的地處理執行個體也不需定義或「擁有」該事件做為類別成員。

WPF 輸入系統會廣泛使用附加事件。 不過,幾乎這所有的附加事件都會轉送到基底元素。 輸入事件接著會顯示為對等的非附加路由事件,其為基底元素類別的成員。 比方說,基礎附加事件 Mouse.MouseDown 可以更輕鬆地使用在上處理 UIElement MouseDownUIElement 而不是在或程式碼中處理附加事件語法 XAML 。

如需 WPF 中附加事件的詳細資訊,請參閱附加事件概觀

XAML 中的完整事件名稱

類似 typename.eventname 附加事件語法的另一種語法用法 (但嚴格來說,它不是附加事件的使用方式) 是,當您連接由子元素所引發之路由事件的處理常式時。 您可將處理常式附加到共同父項,以利用事件路由,即使共同父項可能沒有相關的路由事件做為成員。 再看一下這個範例:

<Border Height="50" Width="300" BorderBrush="Gray" BorderThickness="1">
  <StackPanel Background="LightGray" Orientation="Horizontal" Button.Click="CommonClickHandler">
    <Button Name="YesButton" Width="Auto" >Yes</Button>
    <Button Name="NoButton" Width="Auto" >No</Button>
    <Button Name="CancelButton" Width="Auto" >Cancel</Button>
  </StackPanel>
</Border>

在這裡,加入處理常式的父元素接聽程式為 StackPanel 。 但是,它會為已宣告的路由事件加入處理常式,而類別會引發此事件 Button (ButtonBase 實際上,但是可 Button 透過繼承) 來使用。 Button 「擁有」事件,但是路由事件系統允許將任何路由事件的處理常式附加至任何或實例接聽程式,而這些接聽程式 UIElement ContentElement 可能會附加 common language runtime 的接聽程式 (CLR) 事件。 這些完整事件屬性名稱的預設 xmlns 命名空間通常是預設的 WPF xmlns 命名空間,但您也可以針對自訂路由事件指定有前置詞的命名空間。 如需 xmlns 的詳細資訊,請參閱 WPF XAML 的 XAML 命名空間和命名空間對應

WPF 輸入事件

WPF 平台中有一個路由事件的常用應用程式適用於輸入事件。 在 WPF 中,通道路由事件名稱前面依慣例會加上 "Preview" 這個字。 輸入事件通常會成對出現,其中一個是事件反昇事件,另一個則是通道事件。 例如, KeyDown 事件和 PreviewKeyDown 事件具有相同的簽章,前者是反升輸入事件,後者是通道輸入事件。 有時,輸入事件只會有事件反昇版本,或可能只有直接路由版本。 在文件中,路由事件主題會交互參考具備替代路由傳送策略的類似路由事件 (如果這類路由事件存在),而受管理參考頁面中的章節會釐清每個路由事件的路由傳送策略。

系統會實作成對出現的 WPF 輸入事件,讓來自輸入的單一使用者動作 (例如按下滑鼠按鈕) 將依序引發配對中的這兩個路由事件。 首先,引發通道事件,並周遊其路由。 接著,引發事件反昇事件,並周遊其路由。 這兩個事件實際上會共用相同的事件資料實例,因為在 RaiseEvent 引發反升事件之實類別中的方法呼叫會接聽來自通道事件的事件資料,並在新引發的事件中重複使用它。 具有通道事件處理常式的接聽程式有機會優先將路由事件標示為已處理 (第一個是類別處理常式,然後是執行個體處理常式)。 如果將通道路由中的元素標示為已處理,則已經處理的事件資料就會針對事件反昇事件進行傳送,而且將不會叫用基於對等事件反昇輸入事件附加的一般處理常式。 表面上來看,就如同未曾引發過已處理的事件反昇事件。 這個處理行為非常適用於控制項複合,您可能想要讓您的最終控制項 (而不是它的複合組件) 報告所有以點擊測試為基礎的輸入事件或以焦點為基礎的輸入事件。 最後一個控制項元素更接近複合中的根元素,因此有機會優先對通道事件進行類別處理,而且,或許可利用更專屬於控制項的事件,做為支援控制項類別的程式碼一部分來「取代」該路由事件。

如需輸入事件處理如何運作的圖表說明,請考量下列輸入事件範例。 在下列樹狀結構中, leaf element #2PreviewMouseDown 和事件的來源 MouseDown

事件路由圖表

事件處理的順序如下:

  1. 根元素上的 PreviewMouseDown (通道)。

  2. 中繼元素 #1 上的 PreviewMouseDown (通道)。

  3. 來源元素 #2 上的 PreviewMouseDown (通道)。

  4. 來源元素 #2 上的 MouseDown (事件反昇)。

  5. 中繼元素 #1 上的 MouseDown (事件反昇)。

  6. 根元素上的 MouseDown (事件反昇)。

路由事件處理常式委派提供對兩個物件的參考︰引發事件的物件,以及已叫用處理常式的物件。 已叫用處理常式的物件是 sender 參數所報告的物件。 第一個引發事件的物件是由 Source 事件資料中的屬性所報告。 路由事件仍可由相同的物件引發和處理,在這種情況下,相同的 sender Source (這就是事件處理範例清單中的步驟3和4的情況) 。

由於通道和反升的原因,父項目會接收輸入事件,其中 Source 是其中一個子項目。 重要的是,您必須知道來源元素是什麼,才能藉由存取屬性來識別來源專案 Source

通常,在標記輸入事件之後 Handled ,就不會叫用進一步的處理常式。 一般而言,您應該在叫用處理常式來處理代表輸入事件意義之應用程式特定的邏輯處理之後,儘速將輸入事件標示為已處理。

關於狀態的一般陳述例外 Handled 狀況是,為了刻意忽略事件資料狀態所註冊的輸入事件處理常式, Handled 仍然會沿著任一路由叫用。 如需詳細資訊,請參閱預覽事件將路由事件標記為已處理以及類別處理

通道事件與事件反昇事件之間共用的事件資料模型,以及後續引發的第一個通道事件,然後是事件反昇事件,不是一般適用於所有路由事件的概念。 該行為特別是透過 WPF 輸入裝置如何選擇引發並連接輸入事件配對的方式來實作。 實作您自己的輸入事件是一個進階案例,但您也可以選擇針對自己的輸入事件遵循該模型。

某些類別會選擇對特定輸入事件進行類別處理,一般的用意是重新定義特定使用者驅動的輸入事件在該控制項內所代表的意義,然後引發新的事件。 如需詳細資訊,請參閱將路由事件標記為已處理以及類別處理

如需輸入以及在一般應用程式案例中輸入如何與事件互動的詳細資訊,請參閱輸入概觀

EventSetters 和 EventTriggers

在樣式中,您可以使用,在標記中包含一些預先宣告的 XAML 事件處理語法 EventSetter 。 套用樣式時,會將參考的處理常式加入至樣式執行個體。 您只能 EventSetter 針對路由事件宣告。 以下是一個範例。 請注意,此處參考的 b1SetColor 方法位於程式碼後置檔案中。

<StackPanel
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.EventOvw2"
  Name="dpanel2"
  Initialized="PrimeHandledToo"
>
  <StackPanel.Resources>
    <Style TargetType="{x:Type Button}">
      <EventSetter Event="Click" Handler="b1SetColor"/>
    </Style>
  </StackPanel.Resources>
  <Button>Click me</Button>
  <Button Name="ThisButton" Click="HandleThis">
    Raise event, handle it, use handled=true handler to get it anyway.
  </Button>
</StackPanel>

此處所提供的優點是,樣式可能包含可能套用至應用程式中任何按鈕的大量其他資訊,而使其 EventSetter 成為該樣式的一部分可提升程式碼的重複使用性,即使在標記層級也一樣。 此外, EventSetter 處理常式的抽象化方法名稱會從一般應用程式和頁面標記中進一步移出。

結合路由事件和動畫功能的另一個特製化語法 WPF 是 EventTrigger 。 如同 EventSetter ,只有路由事件可以用於 EventTrigger 。 一般而言, EventTrigger 會宣告為樣式的一部分,但是 EventTrigger 也可以在頁面層級專案上宣告為集合的一部分 Triggers ,或是在中宣告 ControlTemplate 。 可 EventTrigger 讓您指定在 Storyboard 路由事件到達其路由中宣告該事件之的專案時執行的 EventTriggerEventTrigger除了處理事件並使其啟動現有的分鏡腳本之外,還可 EventTrigger 讓您更有效地控制腳本和其執行時間行為。 如需詳細資訊,請參閱在分鏡腳本開始後使用事件觸發程式進行控制

深入了解路由事件

本主題主要是從描述基本概念並提供如何及何時回應路由事件的觀點來討論路由事件,而路由事件已經存在於各種基底元素和控制項中。 不過,您可以在自訂類別上建立自己的路由事件以及所有必要的支援,例如特製化的事件資料類別和委派。 路由事件擁有者可以是任何類別,但是路由事件必須由 UIElementContentElement 衍生類別來引發,才能發揮效用。 如需自訂事件的詳細資訊,請參閱建立自訂路由事件

另請參閱