路由事件概觀

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

必要條件

本主題假設您已瞭解 Common Language Runtime (CLR) 和麵向物件程式設計的基本知識,以及 WPF 元素之間的關聯性如何概念化為樹狀結構的概念。 為了遵循本主題中的範例,您也應該瞭解可延伸的應用程式標記語言(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>

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

Yes, No, and Cancel buttons

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

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

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

路由事件的最上層案例

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

控制群組合和封裝: WPF 中的各種控制項都有豐富的 con帳篷模式l。 例如,您可以將影像放在 的 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 欄位建立為識別碼,以提供不需要靜態或執行時間反映的強固事件識別技術。

路由事件的實作方式

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

下列範例顯示自訂 Tap 路由事件的宣告,包括識別碼欄位的 RoutedEvent 註冊和曝光,以及 add CLR 事件的 和 removeTap 作。

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>

新增標準 CLR 事件處理常式的 XAML 語法與新增路由事件處理常式相同,因為您確實將處理常式新增至 CLR 事件包裝函式,其下方有路由事件實作。 如需在 XAML 中新增事件處理常式的詳細資訊,請參閱 WPF 中的 XAML。

路由傳送策略

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

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

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

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

為什麼要使用路由事件?

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

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

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

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

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

  • 某些 WPF 樣式和範本化功能,例如 EventSetter ,且 EventTrigger 需要參考的事件成為路由事件。 這是先前所述的事件識別碼案例。

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

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

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

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

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

b1SetColor 是實作處理常式的名稱,其中包含處理 Click 事件的程式碼。 b1SetColor 必須具有與 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 將事件處理常式新增至元素的完整範例,請參閱 處理路由事件

在使用程式碼建立的應用程式中加入路由事件的處理常式很簡單。 路由事件處理常式一律可以透過協助程式方法 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 事件處理

已處理的概念

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

的值 Handled 會影響路由事件在沿著路線進一步移動時報告或處理的方式。 如果 Handled 位於 true 路由事件的事件資料中,則接聽其他元素上該路由事件的處理常式通常不會再針對該特定事件實例叫用。 這適用于附加在 XAML 中的處理常式,以及特定語言事件處理常式附件語法所新增的處理常式,例如 +=Handles 。 針對最常見的處理常式案例,將 事件標示為 ,將 設定 Handledtrue 為 會「停止」路由傳送通道路由或反升路由,以及針對類別處理常式在路由中某個時間點處理的任何事件。

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

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

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

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

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

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

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

此概念性設計是由先前所述的路由行為所強化:即使路由上一個處理常式已經設定 Handledtrue 為 ,仍可能以程式碼或樣式附加所叫用之路由事件的處理常式會比較困難。。

如需 Handled 、路由事件的類別處理,以及何時適當將路由事件標示為 Handled 的建議的詳細資訊,請參閱 將路由事件標示為已處理,以及類別處理

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

類別處理常式

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

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

在 WPF 中附加事件

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

WPF 輸入系統會廣泛使用附加事件。 不過,幾乎這所有的附加事件都會轉送到基底元素。 輸入事件接著會顯示為對等的非附加路由事件,其為基底元素類別的成員。 例如,基礎附加事件 Mouse.MouseDown 可以更輕鬆地在任何指定的 UIElementMouseDown 上使用 , UIElement 而不是在 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 #2 是 和 事件 MouseDown 的來源 PreviewMouseDown

Event routing diagram

事件處理的順序如下:

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

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

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

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

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

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

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

由於通道和浮凸,父元素會接收輸入事件,其中 Source 是其中一個子項目。 當知道來源專案是什麼時,您可以存取 Source 屬性來識別來源專案。

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

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

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

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

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

EventSetters 和 EventTriggers

在樣式中,您可以使用 ,在標記 EventSetter 中包含一些預先宣告的 XAML 事件處理語法。 套用樣式時,會將參考的處理常式加入至樣式執行個體。 您只能針對路由事件宣告 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 每當路由事件到達其路由中宣告 EventTrigger 該事件的 時,所執行的 。 除了處理事件並導致它啟動現有的分鏡腳本之外, EventTrigger 的優點是 EventTrigger ,能夠更好地控制分鏡腳本及其執行時間行為。 如需詳細資訊,請參閱在分鏡腳本開始後使用事件觸發程式進行控制

深入了解路由事件

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

另請參閱