Windows Presentation Foundation (WPF) アプリケーション開発者とコンポーネント作成者は、カスタム ルーティング イベントを作成して、共通言語ランタイム (CLR) イベントの機能を拡張できます。 ルーティング イベント機能の詳細については、「ルーティング イベントを 使用する理由」を参照してください。 この記事では、カスタム ルーティング イベントの作成の基本について説明します。
[前提条件]
この記事では、ルーティング イベントに関する基本的な知識と、 ルーティング イベントの概要を読んだことを前提としています。 この記事の例に従うと、拡張アプリケーション マークアップ言語 (XAML) に慣れている場合や、Windows Presentation Foundation (WPF) アプリケーションを記述する方法を理解している場合に役立ちます。
ルーティングされたイベントの手順
ルーティング イベントを作成する基本的な手順は次のとおりです。
RoutedEvent メソッドを使用してRegisterRoutedEventを登録します。
登録呼び出しは、登録されたイベント名、
RoutedEvent
、およびその他のイベントの詳細を保持するルーティング イベント識別子と呼ばれる インスタンスを返します。 静的な読み取り専用フィールドに識別子を割り当てます。 慣例:CLRイベントのaddおよびremoveアクセサーを定義します。 CLR イベント アクセサーがない場合は、 UIElement.AddHandler メソッドと UIElement.RemoveHandler メソッドへの直接呼び出しによってのみ、イベント ハンドラーを追加または削除できます。 CLR イベント アクセサーを使用すると、次のイベント ハンドラーの割り当てメカニズムを取得できます。
- 拡張アプリケーション マークアップ言語 (XAML) では、属性構文を使用してイベント ハンドラーを追加できます。
- C# の場合、
+=
演算子と-=
演算子を使用して、イベント ハンドラーを追加または削除できます。 - VB の場合、 AddHandler ステートメントと RemoveHandler ステートメントを使用して、イベント ハンドラーを追加または削除できます。
ルーティング イベントをトリガーするためのカスタム ロジックを追加します。 たとえば、ロジックによって、ユーザー入力とアプリケーションの状態に基づいてイベントがトリガーされる場合があります。
例
次の例では、カスタム コントロール ライブラリに CustomButton
クラスを実装します。
CustomButton
から派生する Button クラス:
-
RoutedEvent メソッドを使用して
ConditionalClick
という名前のRegisterRoutedEventを登録し、登録時のバブル戦略を指定します。 - 登録呼び出しから返された
RoutedEvent
インスタンスを、ConditionalClickEvent
という名前の静的な読み取り専用フィールドに割り当てます。 - CLR のイベント アクセサーの 追加 と 削除 を定義します。
-
CustomButton
がクリックされ、外部条件が適用されたときにカスタム ルーティング イベントを発生させるカスタム ロジックを追加します。 このコード例では、オーバーライドされたConditionalClick
仮想メソッド内からOnClick
ルーティング イベントを発生させますが、任意の方法でイベントを発生させることができます。
public class CustomButton : Button
{
// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent ConditionalClickEvent = EventManager.RegisterRoutedEvent(
name: "ConditionalClick",
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(CustomButton));
// Provide CLR accessors for assigning an event handler.
public event RoutedEventHandler ConditionalClick
{
add { AddHandler(ConditionalClickEvent, value); }
remove { RemoveHandler(ConditionalClickEvent, value); }
}
void RaiseCustomRoutedEvent()
{
// Create a RoutedEventArgs instance.
RoutedEventArgs routedEventArgs = new(routedEvent: ConditionalClickEvent);
// Raise the event, which will bubble up through the element tree.
RaiseEvent(routedEventArgs);
}
// For demo purposes, we use the Click event as a trigger.
protected override void OnClick()
{
// Some condition combined with the Click event will trigger the ConditionalClick event.
if (DateTime.Now > new DateTime())
RaiseCustomRoutedEvent();
// Call the base class OnClick() method so Click event subscribers are notified.
base.OnClick();
}
}
Public Class CustomButton
Inherits Button
' Register a custom routed event with the Bubble routing strategy.
Public Shared ReadOnly ConditionalClickEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
name:="ConditionalClick",
routingStrategy:=RoutingStrategy.Bubble,
handlerType:=GetType(RoutedEventHandler),
ownerType:=GetType(CustomButton))
' Provide CLR accessors to support event handler assignment.
Public Custom Event ConditionalClick As RoutedEventHandler
AddHandler(value As RoutedEventHandler)
[AddHandler](ConditionalClickEvent, value)
End AddHandler
RemoveHandler(value As RoutedEventHandler)
[RemoveHandler](ConditionalClickEvent, value)
End RemoveHandler
RaiseEvent(sender As Object, e As RoutedEventArgs)
[RaiseEvent](e)
End RaiseEvent
End Event
Private Sub RaiseCustomRoutedEvent()
' Create a RoutedEventArgs instance.
Dim routedEventArgs As New RoutedEventArgs(routedEvent:=ConditionalClickEvent)
' Raise the event, which will bubble up through the element tree.
[RaiseEvent](routedEventArgs)
End Sub
' For demo purposes, we use the Click event as a trigger.
Protected Overrides Sub OnClick()
' Some condition combined with the Click event will trigger the ConditionalClick event.
If Date.Now > New DateTime() Then RaiseCustomRoutedEvent()
' Call the base class OnClick() method so Click event subscribers are notified.
MyBase.OnClick()
End Sub
End Class
この例には、XAML マークアップを使用してCustomButton
のインスタンスをStackPanelに追加し、Handler_ConditionalClick
要素とConditionalClick
要素のCustomButton
イベント ハンドラーとしてStackPanel1
メソッドを割り当てる別の WPF アプリケーションが含まれています。
<Window x:Class="CodeSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:WpfControl;assembly=WpfControlLibrary"
Title="How to create a custom routed event" Height="100" Width="300">
<StackPanel Name="StackPanel1" custom:CustomButton.ConditionalClick="Handler_ConditionalClick">
<custom:CustomButton
Name="customButton"
ConditionalClick="Handler_ConditionalClick"
Content="Click to trigger a custom routed event"
Background="LightGray">
</custom:CustomButton>
</StackPanel>
</Window>
分離コードでは、WPF アプリケーションによって Handler_ConditionalClick
イベント ハンドラー メソッドが定義されます。 イベント ハンドラー メソッドは、分離コードでのみ実装できます。
// The ConditionalClick event handler.
private void Handler_ConditionalClick(object sender, RoutedEventArgs e)
{
string senderName = ((FrameworkElement)sender).Name;
string sourceName = ((FrameworkElement)e.Source).Name;
Debug.WriteLine($"Routed event handler attached to {senderName}, " +
$"triggered by the ConditionalClick routed event raised on {sourceName}.");
}
// Debug output when CustomButton is clicked:
// Routed event handler attached to CustomButton,
// triggered by the ConditionalClick routed event raised on CustomButton.
// Routed event handler attached to StackPanel1,
// triggered by the ConditionalClick routed event raised on CustomButton.
' The ConditionalClick event handler.
Private Sub Handler_ConditionalClick(sender As Object, e As RoutedEventArgs)
Dim sourceName As String = CType(e.Source, FrameworkElement).Name
Dim senderName As String = CType(sender, FrameworkElement).Name
Debug.WriteLine($"Routed event handler attached to {senderName}, " +
$"triggered by the ConditionalClick routed event raised on {sourceName}.")
End Sub
' Debug output when CustomButton is clicked:
' Routed event handler attached to CustomButton,
' triggered by the ConditionalClick routed event raised on CustomButton.
' Routed event handler attached to StackPanel1,
' triggered by the ConditionalClick routed event raised on CustomButton.
CustomButton
がクリックされたとき:
-
ConditionalClick
ルーティング イベントは、CustomButton
で発生します。 -
Handler_ConditionalClick
にアタッチされたCustomButton
イベント ハンドラーがトリガーされます。 -
ConditionalClick
ルーティング イベントは、要素ツリーを上にたどってStackPanel1
します。 -
Handler_ConditionalClick
にアタッチされたStackPanel1
イベント ハンドラーがトリガーされます。 -
ConditionalClick
ルーティング イベントは、他の走査された要素にアタッチされている他のConditionalClick
イベント ハンドラーをトリガーする可能性がある要素ツリーを上に続けます。
Handler_ConditionalClick
イベント ハンドラーは、イベントをトリガーしたイベントに関する次の情報を取得します。
-
sender オブジェクト。イベント ハンドラーがアタッチされている要素です。
sender
は、ハンドラーの初回実行時にCustomButton
され、2 回目の実行時にStackPanel1
されます。 -
RoutedEventArgs.Source オブジェクト。これは、最初にイベントを発生させた要素です。 この例では、
Source
は常にCustomButton
。
注
ルーティング イベントと CLR イベントの主な違いは、ルーティング イベントが要素ツリーを走査し、ハンドラーを探すのに対し、CLR イベントは要素ツリーを走査せず、ハンドラーはイベントを発生させたソース オブジェクトにのみアタッチできることです。 その結果、ルーティング イベント sender
は、要素ツリー内の任意の走査された要素にすることができます。
イベント登録呼び出しでルーティング戦略を Tunnel に設定する以外は、バブル イベントと同じ方法でトンネリング イベントを作成できます。 トンネリング イベントの詳細については、「 WPF 入力イベント」を参照してください。
こちらも参照ください
.NET Desktop feedback