イベントとルーティング イベントの概要Events and routed events overview

重要な APIImportant APIs

使用する場合、Windows ランタイム アプリでのイベントのプログラミングの概念について説明しますC#、Visual Basic または Visual C コンポーネント拡張 (C +/cli CX)、プログラミング言語、および UI の定義を XAML として。We describe the programming concept of events in a Windows Runtime app, when using C#, Visual Basic or Visual C++ component extensions (C++/CX) as your programming language, and XAML for your UI definition. イベントのハンドラーは、UI 要素の宣言の一部として XAML で割り当てることも、コードで追加することもできます。You can assign handlers for events as part of the declarations for UI elements in XAML, or you can add the handlers in code. Windows ランタイムはルーティング イベントをサポートしており、特定の入力イベントとデータ イベントを、その発生元オブジェクト以外のオブジェクトで処理できます。Windows Runtime supports routed events: certain input events and data events can be handled by objects beyond the object that fired the event. ルーティング イベントは、コントロール テンプレートを定義する際や、ページまたはレイアウト コンテナーを使う際に役立ちます。Routed events are useful when you define control templates, or use pages or layout containers.

プログラミングの概念としてのイベントEvents as a programming concept

一般に、Windows ランタイム アプリのプログラミングを行う際のイベントの概念は、最も一般的なプログラミング言語のイベント モデルと似ています。Generally speaking, event concepts when programming a Windows Runtime app are similar to the event model in most popular programming languages. Microsoft .NET または C++ のイベントの操作方法を把握していれば、スムーズに理解できます。If you know how to work with Microsoft .NET or C++ events already, you have a head start. ただし、ハンドラーのアタッチのような基本的なタスクを行うために、イベント モデルの概念について詳しく学ぶ必要はありません。But you don't need to know that much about event model concepts to perform some basic tasks, such as attaching handlers.

プログラミング言語として C#、Visual Basic、または C++/CX を使用する場合、UI はマークアップ (XAML) で定義されます。When you use C#, Visual Basic or C++/CX as your programming language, the UI is defined in markup (XAML). XAML マークアップの構文で、マークアップ要素とランタイム コード エンティティの間でイベントを関連付けるときの原則の一部は、他の Web テクノロジ (ASP.NET、HTML5 など) と似ています。In XAML markup syntax, some of the principles of connecting events between markup elements and runtime code entities are similar to other Web technologies, such as ASP.NET, or HTML5.

  XAML 定義の UI のランタイム ロジックを提供するコードと呼ばコード ビハインドまたは分離コード ファイル。Note  The code that provides the runtime logic for a XAML-defined UI is often referred to as code-behind or the code-behind file. Microsoft Visual Studio のソリューション ビューでは、コード ビハインド ファイルが参照先の XAML ページに対して依存する入れ子のファイルとして表示されて、この関係がグラフィカルに示されます。In the Microsoft Visual Studio solution views, this relationship is shown graphically, with the code-behind file being a dependent and nested file versus the XAML page it refers to.

Button.Click: イベントと XAML の概要Button.Click: an introduction to events and XAML

Windows ランタイム アプリの最も一般的なプログラミング タスクの 1 つは、ユーザー入力を UI に取り込むことです。One of the most common programming tasks for a Windows Runtime app is to capture user input to the UI. たとえば、UI には、ユーザーが情報を送信、または状態を変更するためにクリックする必要のあるボタンが組み込まれることがあります。For example, your UI might have a button that the user must click to submit info or to change state.

Windows ランタイム アプリの UI を定義するには、XAML を生成します。You define the UI for your Windows Runtime app by generating XAML. この XAML は、通常は Visual Studio のデザイン サーフェイスからの出力です。This XAML is usually the output from a design surface in Visual Studio. また、プレーンテキスト エディターやサードパーティ製の XAML エディターで記述することもできます。You can also write the XAML in a plain-text editor or a third-party XAML editor. この XAML を生成するときに、個々の UI 要素のプロパティ値を設定するすべての XAML 属性を定義する際に、その UI 要素にイベント ハンドラーを関連付けることができます。While generating that XAML, you can wire event handlers for individual UI elements at the same time that you define all the other XAML attributes that establish property values of that UI element.

XAML でイベントを記述する場合は、コード ビハインドで既に定義してあるものも、これから定義するものも含め、ハンドラー メソッドの文字列形式の名前を指定します。To wire the events in XAML, you specify the string-form name of the handler method that you've already defined or will define later in your code-behind. たとえば、この XAML は、他のプロパティ (x:Name 属性コンテンツ) を属性として割り当てたうえでボタン オブジェクトを定義し、ShowUpdatesButton_Click というメソッドを参照してボタンのクリック イベントのハンドラーを関連付けます。For example, this XAML defines a Button object with other properties (x:Name attribute, Content) assigned as attributes, and wires a handler for the button's Click event by referencing a method named ShowUpdatesButton_Click:

<Button x:Name="showUpdatesButton"
  Content="{Binding ShowUpdatesText}"
  Click="ShowUpdatesButton_Click"/>

ヒント:   イベントの関連付けは、プログラミング用語です。Tip  Event wiring is a programming term. これは、イベントが発生して名前付けされたハンドラー メソッドを呼び出すことを示すプロセスやコードのことを指します。It refers to the process or code whereby you indicate that occurrences of an event should invoke a named handler method. ほとんどの手続き型コード モデルで、イベントの関連付けはイベントとメソッドの両方の名前を付ける暗黙的または明示的な "AddHandler" コードで、通常ターゲット オブジェクト インスタンスが関係しています。In most procedural code models, event wiring is implicit or explicit "AddHandler" code that names both the event and method, and usually involves a target object instance. XAML では、「AddHandler」は暗黙的であり、イベントの関連付けは、すべてオブジェクト要素の属性名としてのイベントの名前付けと、属性値としてのハンドラーの名前付けで構成されています。In XAML, the "AddHandler" is implicit, and event wiring consists entirely of naming the event as the attribute name of an object element, and naming the handler as that attribute's value.

実際のハンドラーは、アプリのすべてのコードとコード ビハインドで使っているプログラミング言語で記述します。You write the actual handler in the programming language that you're using for all your app's code and code-behind. ここでは、Click="ShowUpdatesButton_Click" という属性を使ってコントラクトを作成しています。このコントラクトにより、XAML のマークアップ コンパイルと解析の際に、IDE のビルド アクションの XAML マークアップ コンパイル ステップと、アプリの読み込み時の最終的な XAML の解析で、ShowUpdatesButton_Click という名前のメソッドをアプリのコードの中から検出できます。With the attribute Click="ShowUpdatesButton_Click", you have created a contract that when the XAML is markup-compiled and parsed, both the XAML markup compile step in your IDE's build action and the eventual XAML parse when the app loads can find a method named ShowUpdatesButton_Click as part of the app's code. ShowUpdatesButton_Click は、Click イベントのすべてのハンドラーに対応したメソッド シグネチャを (デリゲートに基づいて) 実装するメソッドであることが必要です。ShowUpdatesButton_Click must be a method that implements a compatible method signature (based on a delegate) for any handler of the Click event. たとえば、次のコードは ShowUpdatesButton_Click ハンドラーを定義します。For example, this code defines the ShowUpdatesButton_Click handler.

private void ShowUpdatesButton_Click (object sender, RoutedEventArgs e) 
{
    Button b = sender as Button;
    //more logic to do here...
}
Private Sub ShowUpdatesButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim b As Button = CType(sender, Button)
    '  more logic to do here...
End Sub
void winrt::MyNamespace::implementation::BlankPage::ShowUpdatesButton_Click(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& e)
{
    auto b{ sender.as<Windows::UI::Xaml::Controls::Button>() };
    // More logic to do here.
}
void MyNamespace::BlankPage::ShowUpdatesButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) 
{
    Button^ b = (Button^) sender;
    //more logic to do here...
}

この例では、ShowUpdatesButton_Click メソッドは RoutedEventHandler デリゲートに基づいています。In this example, the ShowUpdatesButton_Click method is based on the RoutedEventHandler delegate. MSDN のリファレンス ページで、Click メソッドの構文にこのデリゲートが指定されているため、このデリゲートを使います。You'd know that this is the delegate to use because you'll see that delegate named in the syntax for the Click method on the MSDN reference page.

ヒント:   Visual Studio には、イベント ハンドラーの名前を指定し、XAML を編集すると、ハンドラー メソッドを定義する便利な方法が用意されています。Tip  Visual Studio provides a convenient way to name the event handler and define the handler method while you're editing XAML. XAML テキスト エディターでイベントの属性名を入力する際には、Microsoft IntelliSense リストが表示されるまで少し待ってください。When you provide the attribute name of the event in the XAML text editor, wait a moment until a Microsoft IntelliSense list displays. リストの [<新しいイベント ハンドラー>] をクリックすると、要素の x:Name (または型名) に基づいて、メソッド名、イベント名、数値サフィックスの候補が表示されます。If you click <New Event Handler> from the list, Microsoft Visual Studio will suggest a method name based on the element's x:Name (or type name), the event name, and a numeric suffix. その後、選択したイベント ハンドラー名を右クリックし、 [イベント ハンドラーへ移動] をクリックできます。You can then right-click the selected event handler name and click Navigate to Event Handler. そうすると、新たに挿入されたイベント ハンドラー定義に直接移動します。これは、XAML ページのコード ビハインド ファイルのコード エディター ビューで確認できます。This will navigate directly to the newly inserted event handler definition, as seen in the code editor view of your code-behind file for the XAML page. イベント ハンドラーには既に正しいシグネチャが設定されています (sender パラメーターや、イベントが使う特定のイベント データ クラスなど)。The event handler already has the correct signature, including the sender parameter and the event data class that the event uses. また、正しいシグネチャを持つハンドラー メソッドが既にコード ビハインド内に存在する場合は、メソッドの名前が [<新しいイベント ハンドラー>] オプションと共にオート コンプリート ドロップダウンに表示されます。Also, if a handler method with the correct signature already exists in your code-behind, that method's name appears in the auto-complete drop-down along with the <New Event Handler> option. また、IntelliSense のリスト項目をクリックする代わりに、ショートカットとして Tab キーを押すこともできます。You can also press the Tab key as a shortcut instead of clicking the IntelliSense list items.

イベント ハンドラーの定義Defining an event handler

オブジェクトが UI 要素であり、XAML で宣言される場合、イベント ハンドラー コードは、XAML ページのコード ビハインドとなる部分クラスに定義します。For objects that are UI elements and declared in XAML, event handler code is defined in the partial class that serves as the code-behind for a XAML page. イベント ハンドラーは、XAML に関連付けられた部分クラスの一部として記述するメソッドです。Event handlers are methods that you write as part of the partial class that is associated with your XAML. これらのイベント ハンドラーは、特定のイベントが使用するデリゲートに基づきます。These event handlers are based on the delegates that a particular event uses. イベント ハンドラー メソッドは、public と private のどちらでもかまいません。Your event handler methods can be public or private. アクセス レベルを private に設定できるのは、XAML によって作成されるハンドラーとインスタンスが最終的にコード生成によって結合されるためです。Private access works because the handler and instance created by the XAML are ultimately joined by code generation. 通常は、イベント ハンドラー メソッドをクラス内で private にすることをお勧めします。In general, we recommend that you make your event handler methods private in the class.

  C++ 用のイベント ハンドラーは、部分クラスで定義を取得しない、プライベート クラス メンバーとして、ヘッダーで宣言されています。Note  Event handlers for C++ don't get defined in partial classes, they are declared in the header as a private class member. C++ プロジェクトのビルド アクションでは、XAML の型システムと C++ のコード ビハインド モデルをサポートするコードが生成されます。The build actions for a C++ project take care of generating code that supports the XAML type system and code-behind model for C++.

sender パラメーターとイベント データThe sender parameter and event data

イベント用に記述したハンドラーは、そのハンドラーが呼び出された際に、その都度入力として使える 2 つの値にアクセスできます。The handler you write for the event can access two values that are available as input for each case where your handler is invoked. その最初の値が sender です。これは、ハンドラーがアタッチされているオブジェクトへの参照です。The first such value is sender, which is a reference to the object where the handler is attached. sender パラメーターは、Object 基本型として型指定されます。The sender parameter is typed as the base Object type. sender をより正確な型にキャストするという手法がよく使用されます。A common technique is to cast sender to a more precise type. この手法は、sender オブジェクト自体で状態を確認または変更する必要がある場合に便利です。This technique is useful if you expect to check or change state on the sender object itself. 通常は、それぞれのアプリ設計に基づき、sender のキャスト先として安全な型をハンドラーのアタッチ先やその他の設計の情報を基に把握します。Based on your own app design, you usually know a type that is safe to cast sender to, based on where the handler is attached or other design specifics.

2 つ目の値はイベント データです。これは通常、e パラメーターとして構文の定義に表示されます。The second value is event data, which generally appears in syntax definitions as the e parameter. 使用できるイベント データのプロパティを見つけるには、処理対象のイベントに割り当てられているデリゲートの e パラメーターを参照した後、Visual Studio の IntelliSense かオブジェクト ブラウザーを使います。You can discover which properties for event data are available by looking at the e parameter of the delegate that is assigned for the specific event you are handling, and then using IntelliSense or Object Browser in Visual Studio. Windows ランタイム リファレンス ドキュメントを使うこともできます。Or you can use the Windows Runtime reference documentation.

イベントによっては、イベントの発生を検知することと同様にイベント データの特定のプロパティ値が重要となります。For some events, the event data's specific property values are as important as knowing that the event occurred. これが特に当てはまるのが入力イベントです。This is especially true of the input events. ポインター イベントの場合は、イベントが発生したときのポインターの位置が重要です。For pointer events, the position of the pointer when the event occurred might be important. キーボード イベントの場合、キーボード上のいずれのキーが押されても KeyDown イベントと KeyUp イベントが発生します。For keyboard events, all possible key presses fire a KeyDown and KeyUp event. ユーザーがどのキーを押したかを判定するには、イベント ハンドラーで使うことができる KeyRoutedEventArgs にアクセスする必要があります。To determine which key a user pressed, you must access the KeyRoutedEventArgs that is available to the event handler. 入力イベントの処理について詳しくは、「キーボード操作」と「ポインター入力の処理」をご覧ください。For more info about handling input events, see Keyboard interactions and Handle pointer input. 入力イベントと入力シナリオに対処するには、通常、ポインター イベントのポインター キャプチャや、キーボード イベントの修飾キーとプラットフォーム キー コードなど、このトピックで取り上げていない事柄についても考慮する必要があります。Input events and input scenarios often have additional considerations that are not covered in this topic, such as pointer capture for pointer events, and modifier keys and platform key codes for keyboard events.

async パターンを使うイベント ハンドラーEvent handlers that use the async pattern

ときには、イベント ハンドラー内で async パターンを使う API を使う必要が生じることもあります。In some cases you'll want to use APIs that use an async pattern within an event handler. たとえば、ファイル ピッカーを表示して操作するには、AppBarButton を使います。For example, you might use a Button in an AppBar to display a file picker and interact with it. ただし、ファイル ピッカー API の多くは非同期です。However, many of the file picker APIs are asynchronous. それらの API は async/awaitable スコープ内で呼び出す必要があります。これはコンパイラの要件になります。They have to be called within an async/awaitable scope, and the compiler will enforce this. 追加するには何ができるように、 asyncイベント ハンドラーにキーワード、ハンドラーが今すぐ非同期 voidSo what you can do is add the async keyword to your event handler such that the handler is now async void. これで、イベント ハンドラーは async/awaitable での呼び出しが可能になります。Now your event handler is permitted to make async/awaitable calls.

async パターンを使ったユーザー操作イベントの処理の例については、「ファイル アクセスとファイル ピッカー」(「C# または Visual Basic を使った初めての Windows ランタイム アプリの作成」シリーズの一部) をご覧ください。For an example of user-interaction event handling using the async pattern, see File access and pickers (part of theCreate your first Windows Runtime app using C# or Visual Basic series). 「C での非同期 API の呼び出し」もご覧ください。See also [Call asynchronous APIs in C).

コードでのイベント ハンドラーの追加Adding event handlers in code

イベント ハンドラーをオブジェクトに割り当てる手段は、XAML 以外にもあります。XAML is not the only way to assign an event handler to an object. イベント ハンドラーをコードで特定のオブジェクト (XAML では使用できないオブジェクトも含む) に追加するには、言語固有のイベント ハンドラー追加構文を使用します。To add event handlers to any given object in code, including to objects that are not usable in XAML, you can use the language-specific syntax for adding event handlers.

C# の構文では、+= 演算子を使用します。In C#, the syntax is to use the += operator. 演算子の右側でイベント ハンドラー メソッド名を参照することによって、ハンドラーを登録します。You register the handler by referencing the event handler method name on the right side of the operator.

ランタイム UI に表示されるオブジェクトにイベント ハンドラーをコードで追加する場合、LoadedOnApplyTemplate など、オブジェクトの有効期間イベントまたはコールバックに応じてハンドラーを追加するのが一般的です。これにより、該当するオブジェクトのイベント ハンドラーは、実行時にユーザーが発生させるイベントに対応できるようになります。If you use code to add event handlers to objects that appear in the run-time UI, a common practice is to add such handlers in response to an object lifetime event or callback, such as Loaded or OnApplyTemplate, so that the event handlers on the relevant object are ready for user-initiated events at run time. 次の例は、ページ構造の XAML の概略と、イベント ハンドラーをオブジェクトに追加するための C# 言語の構文を示しています。This example shows a XAML outline of the page structure and then provides the C# language syntax for adding an event handler to an object.

<Grid x:Name="LayoutRoot" Loaded="LayoutRoot_Loaded">
  <StackPanel>
    <TextBlock Name="textBlock1">Put the pointer over this text</TextBlock>
...
  </StackPanel>
</Grid>
void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
    textBlock1.PointerEntered += textBlock1_PointerEntered;
    textBlock1.PointerExited += textBlock1_PointerExited;
}

  より詳細な構文が存在します。Note  A more verbose syntax exists. 2005 年に、コンパイラで新しいデリゲート インスタンスを推論できるようにするデリゲートの推論という機能が C# に追加されて、上のより単純な形式の構文を使えるようになりました。In 2005, C# added a feature called delegate inference, which enables a compiler to infer the new delegate instance and enables the previous, simpler syntax. 冗長な構文は、機能的には上の例と同じですが、新しいデリゲート インスタンスを登録する前に明示的に作成します。したがって、デリゲートの推論は使用されません。The verbose syntax is functionally identical to the previous example, but explicitly creates a new delegate instance before registering it, thus not taking advantage of delegate inference. この明示的な構文は、あまり一般的ではありませんが、コード例で使わることがあります。This explicit syntax is less common, but you might still see it in some code examples.

void LayoutRoot_Loaded(object sender, RoutedEventArgs e)
{
    textBlock1.PointerEntered += new PointerEventHandler(textBlock1_PointerEntered);
    textBlock1.PointerExited += new MouseEventHandler(textBlock1_PointerExited);
}

Visual Basic 構文の場合は 2 とおりの方法があります。There are two possibilities for Visual Basic syntax. 1 つは、C# 構文と同じように記述し、ハンドラーを直接インスタンスにアタッチする方法です。One is to parallel the C# syntax and attach handlers directly to instances. この場合は、AddHandler キーワードに加え、ハンドラー メソッド名を逆参照する AddressOf 演算子が必要です。This requires the AddHandler keyword and also the AddressOf operator that dereferences the handler method name.

もう 1 つは、イベント ハンドラーに Handles キーワードを指定するという方法です。The other option for Visual Basic syntax is to use the Handles keyword on event handlers. この方法は、読み込みの時点からオブジェクトの有効期間を通じてオブジェクト上にハンドラーが存在している必要がある場合に適しています。This technique is appropriate for cases where handlers are expected to exist on objects at load time and persist throughout the object lifetime. XAML に定義されたオブジェクトで Handles を使うには、Name / x:Name を指定する必要があります。Using Handles on an object that is defined in XAML requires that you provide a Name / x:Name. この名前は、Handles 構文の Instance.Event 部分に必要なインスタンス修飾子となります。This name becomes the instance qualifier that is needed for the Instance.Event part of the Handles syntax. この場合は、他のイベント ハンドラーのアタッチを開始する、オブジェクトの有効期間に基づくイベント ハンドラーは不要です。Handles の関連付けは、XAML ページのコンパイル時に作成されます。In this case you don't need an object lifetime-based event handler to initiate attaching the other event handlers; the Handles connections are created when you compile your XAML page.

Private Sub textBlock1_PointerEntered(ByVal sender As Object, ByVal e As PointerRoutedEventArgs) Handles textBlock1.PointerEntered
' ...
End Sub

  昇格の代わりにインスタンス処理手法が一般に Visual Studio およびその XAML デザイン画面、処理キーワード。Note  Visual Studio and its XAML design surface generally promote the instance-handling technique instead of the Handles keyword. その理由は、XAML でのイベント ハンドラーの関連付けがデザイナーと開発者が対処する一般的なワークフローに含まれるだけでなく、Handles キーワードを使用する手法に XAML でのイベント ハンドラーの関連付けとの互換性がないためです。This is because establishing the event handler wiring in XAML is part of typical designer-developer workflow, and the Handles keyword technique is incompatible with wiring the event handlers in XAML.

C++/cli CX、使用することも、 += 構文基本的なから違いがありますが、C#フォーム。In C++/CX, you also use the += syntax, but there are differences from the basic C# form:

  • デリゲートの推論は行われないため、ref new でデリゲート インスタンスを作成する必要があります。No delegate inference exists, so you must use ref new for the delegate instance.
  • デリゲート コンストラクターにパラメーターが 2 つあり、最初のパラメーターでターゲット オブジェクトを指定する必要があります。The delegate constructor has two parameters, and requires the target object as the first parameter. 通常は this を指定します。Typically you specify this.
  • デリゲート コンストラクターの 2 番目のパラメーターにはメソッドのアドレスを指定する必要があるため、メソッド名の前に & 参照演算子を付けます。The delegate constructor requires the method address as the second parameter, so the & reference operator precedes the method name.
textBlock1().PointerEntered({this, &MainPage::TextBlock1_PointerEntered });
textBlock1->PointerEntered += 
ref new PointerEventHandler(this, &BlankPage::textBlock1_PointerEntered);

コードでのイベント ハンドラーの削除Removing event handlers in code

イベント ハンドラーをコードで追加した場合であっても、通常はコード内のイベント ハンドラーを削除する必要はありません。It's not usually necessary to remove event handlers in code, even if you added them in code. ページやコントロールなど、ほとんどの Windows ランタイム オブジェクトには、その有効期間の動作として、メインの Window とそのビジュアル ツリーから切断されると破棄されるという動作が備わっています。また、デリゲート参照がある場合には、それも破棄されます。The object lifetime behavior for most Windows Runtime objects such as pages and controls will destroy the objects when they are disconnected from the main Window and its visual tree, and any delegate references are destroyed too. これには、.NET であればガベージ コレクション、C++/CX を備えた Windows ランタイムであれば弱参照が、それぞれ既定で使われます。.NET does this through garbage collection and Windows Runtime with C++/CX uses weak references by default.

まれに、イベント ハンドラーを明示的に削除する必要が生じることがあります。There are some rare cases where you do want to remove event handlers explicitly. 次のようなクラスがあります。These include:

  • 静的イベントのためにハンドラーを追加したものの、従来の方法でガベージ コレクションを実行できない。Handlers you added for static events, which can't get garbage-collected in a conventional way. Windows ランタイム API の静的イベントの例は、CompositionTarget クラスと Clipboard クラスのイベントです。Examples of static events in the Windows Runtime API are the events of the CompositionTarget and Clipboard classes.
  • テスト コードでハンドラーの削除のタイミングを即時にする必要がある、またはコードで実行時にイベントの古いイベント ハンドラーを新しいものに置き換える必要がある。Test code where you want the timing of handler removal to be immediate, or code where you what to swap old/new event handlers for an event at run time.
  • カスタム remove アクセサーを実装する。The implementation of a custom remove accessor.
  • カスタム静的イベント。Custom static events.
  • ページ ナビゲーションのハンドラー。Handlers for page navigations.

FrameworkElement.Unloaded または Page.NavigatedFrom 状態管理とオブジェクト有効期間中にこのような適切な位置がある可能性のあるイベントのトリガー他のイベント ハンドラーを削除するために使用できます。FrameworkElement.Unloaded or Page.NavigatedFrom are possible event triggers that have appropriate positions in state management and object lifetime such that you can use them for removing handlers for other events.

名前付きイベント ハンドラーを削除するなど、 textBlock1_PointerEnteredターゲット オブジェクトからtextBlock1このコードを使用します。For example, you can remove an event handler named textBlock1_PointerEntered from the target object textBlock1 using this code.

textBlock1.PointerEntered -= textBlock1_PointerEntered;
RemoveHandler textBlock1.PointerEntered, AddressOf textBlock1_PointerEntered

また、XAML 属性によってイベントが追加された場合 (つまり、生成されたコードにハンドラーが追加された場合) にも、ハンドラーを削除できます。You can also remove handlers for cases where the event was added through a XAML attribute, which means that the handler was added in generated code. ハンドラーがアタッチされた要素に Name 値を指定した場合には、後でコードにオブジェクト参照が設定されるため、こちらの方法の方が簡単です。ただし、オブジェクトに Name がない場合は、必要なオブジェクト参照を探すにあたって、オブジェクト ツリーを辿るという方法もあります。This is easier to do if you provided a Name value for the element where the handler was attached, because that provides an object reference for code later; however, you could also walk the object tree in order to find the necessary object reference in cases where the object has no Name.

C++/CX でイベント ハンドラーを削除する場合には、登録トークンが必要です。このトークンは、+= イベント ハンドラー登録の戻り値から受け取ります。If you need to remove an event handler in C++/CX, you'll need a registration token, which you should've received from the return value of the += event handler registration. メソッド名ではなく、C++/CX の構文で -= 登録解除の右側に使われる値がトークンであるためです。That's because the value you use for the right side of the -= deregistration in the C++/CX syntax is the token, not the method name. C++/CX で生成されたコードではトークンが保存されないため、C++/CX では、XAML 属性として追加されたハンドラーを削除できません。For C++/CX, you can't remove handlers that were added as a XAML attribute because the C++/CX generated code doesn't save a token.

ルーティング イベントRouted events

Windows ランタイムと C#、Microsoft Visual Basic、または C++/CX では、ほとんどの UI 要素に存在する一連のイベントのルーティング イベントの概念がサポートされています。The Windows Runtime with C#, Microsoft Visual Basic or C++/CX supports the concept of a routed event for a set of events that are present on most UI elements. これらのイベントは、入力やユーザー操作のシナリオ用であり、UIElement 基底クラスに実装されています。These events are for input and user interaction scenarios, and they are implemented on the UIElement base class. ルーティング イベントである入力イベントの一覧を次に示します。Here's a list of input events that are routed events:

ルーティング イベントとは、オブジェクト ツリーの子オブジェクトから渡され (ルーティングされ)、一連の親オブジェクトまでルーティングされる可能性のあるイベントのことです。A routed event is an event that is potentially passed on (routed) from a child object to each of its successive parent objects in an object tree. UI の XAML 構造はこのツリーに類似した構造となり、このツリーのルートは XAML におけるルート要素に相当します。The XAML structure of your UI approximates this tree, with the root of that tree being the root element in XAML. 実際のオブジェクト ツリーは、プロパティ要素タグなどの XAML 言語機能が含まれていないので、XAML 要素のネスト構造とはやや異なります。The true object tree might vary somewhat from the XAML element nesting, because the object tree doesn't include XAML language features such as property element tags. ルーティング イベントは、イベント発生元の XAML オブジェクト子要素からその親オブジェクト要素へとバブル ルーティングされるイベントと考えることができます。You can conceive of the routed event as bubbling from any XAML object element child element that fires the event, toward the parent object element that contains it. イベントとそのイベント データはイベント ルートをたどって複数のオブジェクトで処理される場合があります。The event and its event data can be handled on multiple objects along the event route. どの要素にもハンドラーがない場合は、ルート要素に達するまでイベント ルートをたどっていくことになります。If no element has handlers, the route potentially keeps going until the root element is reached.

ダイナミック HTML (DHTML) や HTML5 などの Web テクノロジについて知識がある場合は、既にバブル イベントの概念をご存じかもしれません。If you know Web technologies such as Dynamic HTML (DHTML) or HTML5, you might already be familiar with the bubbling event concept.

ルーティング イベントがイベント ルートをたどってバブル ルーティングされるとき、アタッチされたすべてのイベント ハンドラーはイベント データのインスタンスを共有し、同じインスタンスにアクセスします。When a routed event bubbles through its event route, any attached event handlers all access a shared instance of event data. したがって、ハンドラーによる書き込みが可能なイベント データがある場合は、イベント データが変更されると変更後のイベント データが次のハンドラーに渡されるため、そのイベントの元のイベント データを表さなくなる可能性があります。Therefore, if any of the event data is writeable by a handler, any changes made to event data will be passed on to the next handler, and may no longer represent the original event data from the event. ルーティング イベントの動作を持つイベントは、リファレンス ドキュメントにルーティング動作に関する注釈が含まれています。When an event has a routed event behavior, the reference documentation will include remarks or other notations about the routed behavior.

RoutedEventArgsOriginalSource プロパティThe OriginalSource property of RoutedEventArgs

イベントがバブル ルーティングによって移動すると、sender はイベントが発生したオブジェクトと同じものではなくなります。When an event bubbles up an event route, sender is no longer the same object as the event-raising object. sender は、呼び出されたハンドラーがアタッチされているオブジェクトです。Instead, sender is the object where the handler that is being invoked is attached.

場合によっては、注目されるのは sender ではなく、ポインター イベントが発生したときにどの子オブジェクトにポインターが置かれているかや、ユーザーがキーボードのキーを押したときに上位の UI のどのオブジェクトにフォーカスがあったかなどの情報です。In some cases, sender is not interesting, and you are instead interested in info such as which of the possible child objects the pointer is over when a pointer event fired, or which object in a larger UI held focus when a user pressed a keyboard key. そのような場合には、OriginalSource プロパティの値を利用できます。For these cases, you can use the value of the OriginalSource property. OriginalSource は、ルートのすべての位置で、ハンドラーがアタッチされているオブジェクトではなく、イベントを発生させた元のオブジェクトを報告します。At all points on the route, OriginalSource reports the original object that fired the event, instead of the object where the handler is attached. ただし、UIElement の入力イベントでは、そのイベント発生元のオブジェクトはページ レベルの UI 定義 XAML ですぐに見つかるオブジェクトではありません。However, for UIElement input events, that original object is often an object that is not immediately visible in the page-level UI definition XAML. コントロールのテンプレート パーツである場合もよくあります。Instead, that original source object might be a templated part of a control. たとえば、ユーザーが Button の端にポインターをホバーした場合、ほとんどのポインター イベントでは、OriginalSourceButton そのものではなく、TemplateBorder テンプレート パーツになります。For example, if the user hovers the pointer over the very edge of a Button, for most pointer events the OriginalSource is a Border template part in the Template, not the Button itself.

ヒント:   バブル入力イベントは、template 宣言されたコントロールを作成する場合に特に便利です。Tip  Input event bubbling is especially useful if you are creating a templated control. テンプレート化されたすべてのコントロールでは、ユーザーによって新しいテンプレートが適用される可能性があるためです。Any control that has a template can have a new template applied by its consumer. 作業テンプレートを再作成しようとしているユーザーによって、既定のテンプレートで宣言されているイベント処理が誤って削除される可能性もあるためです。The consumer that's trying to recreate a working template might unintentionally eliminate some event handling declared in the default template. そのような場合でも、クラス定義内でオーバーライドした OnApplyTemplate の一部としてハンドラーをアタッチすることで、コントロール レベルのイベント処理を提供できます。You can still provide control-level event handling by attaching handlers as part of the OnApplyTemplate override in the class definition. これにより、インスタンス化時にコントロールのルートまでバブル ルーティングされる入力イベントをキャッチできます。Then you can catch the input events that bubble up to the control's root on instantiation.

Handled プロパティThe Handled property

特定のルーティング イベントのイベント データ クラスには、Handled というプロパティが含まれているものがあります。Several event data classes for specific routed events contain a property named Handled. その例として、PointerRoutedEventArgs.HandledKeyRoutedEventArgs.HandledDragEventArgs.Handled があります。For examples, see PointerRoutedEventArgs.Handled, KeyRoutedEventArgs.Handled, DragEventArgs.Handled. これらのどのクラスでも、Handled は設定可能なブール型プロパティとして使用されます。In all cases Handled is a settable Boolean property.

Handled プロパティを true に設定すると、イベント システムの動作に影響します。Setting the Handled property to true influences the event system behavior. Handledtrue に設定されると、その時点でほとんどのイベント ハンドラーへのイベントのルーティングは停止し、それ以降イベントはルート上にあるアタッチされている他のハンドラーによってキャッチされなくなります。When Handled is true, the routing stops for most event handlers; the event doesn't continue along the route to notify other attached handlers of that particular event case. "Handled" になったときイベントのコンテキストでどのような結果になるか、またアプリがどのように応答するかは、アプリの設計しだいです。What "handled" means in the context of the event and how your app responds to it is up to you. 基本的に Handled は、イベントの発生時にそのイベントをどのコンテナーにもバブル ルーティングする必要がないことをアプリのコードで指定できるシンプルなプロトコルです。そのときに何を実行する必要があるかはアプリのロジックで扱います。Basically, Handled is a simple protocol that enables app code to state that an occurrence of an event doesn't need to bubble to any containers, your app logic has taken care of what needs done. ただし逆に注意すべきなのは、組み込みシステムやコントロールの動作用にバブル ルーティングが必要になることが多いイベントは処理しないということです。たとえば、選択コントロールの一部または項目内での低レベルのイベントを処理することで悪影響が出る場合があります。Conversely though, you do have to be careful that you aren't handling events that probably should bubble so that built-in system or control behaviors can act. For example, handling low-level events within the parts or items of a selection control can be detrimental. 選択コントロールは入力イベントを検索して選択の変更を調べる場合があるためです。The selection control might be looking for input events to know that the selection should change.

一部のルーティング イベントではこの方法でルーティングを停止できません。それらのイベントに Handled プロパティがないためです。Not all of the routed events can cancel a route in this way, and you can tell that because they won't have a Handled property. たとえば、GotFocusLostFocus はバブル ルーティングされますが、対応するイベント データ クラスにルーティングを停止する Handled プロパティがないため、常にルートまでバブル ルーティングされます。For example, GotFocus and LostFocus do bubble, but they always bubble all the way to the root, and their event data classes don't have a Handled property that can influence that behavior.

コントロールの入力イベント ハンドラーInput event handlers in controls

特定の Windows ランタイム コントロールでは、入力イベントに Handled の概念が内部的に使用されていることがあります。Specific Windows Runtime controls sometimes use the Handled concept for input events internally. このような場合、ユーザー コードからはそれを操作できないので、入力イベントが発生することはないようにも見えます。This can make it seem like an input event never occurs, because your user code can't handle it. たとえば、Button クラスには、一般的な入力イベント PointerPressed を意図的に処理するロジックが含まれています。For example, the Button class includes logic that deliberately handles the general input event PointerPressed. これは、PointerPressed 入力やその他の入力モード (たとえば、フォーカスがあるときにボタンを起動できる、Enter キーなどのキーの処理) によって開始される Click イベントを、ボタンが発生させるためです。It does so because buttons fire a Click event that is initiated by pointer-pressed input, as well as by other input modes such as handling keys like the Enter key that can invoke the button when it's focused. Button クラスの設計上、未加工入力イベントは概念的に処理され、ユーザー コードなどのクラス コンシューマーは、コントロール関連の Click イベントとやり取りできます。For purposes of the class design of Button, the raw input event is conceptually handled, and class consumers such as your user code can instead interact with the control-relevant Click event. Windows ランタイム API リファレンスでは、特定のコントロール クラスのリファレンス トピックに、そのクラスが実装しているイベント処理動作の説明が含まれています。Topics for specific control classes in the Windows Runtime API reference often note the event handling behavior that the class implements. 場合によっては、*On***Event メソッドをオーバーライドすることで、動作を変更できます。In some cases, you can change the behavior by overriding *On***Event methods. たとえば、TextBox 派生クラスがキー入力に対してどう反応するかは、Control.OnKeyDown をオーバーライドすることで変更できます。For example, you can change how your TextBox derived class reacts to key input by overriding Control.OnKeyDown.

処理済みのルーティング イベントに対するハンドラー登録Registering handlers for already-handled routed events

既に説明したように、Handledtrue に設定すると、ほとんどのハンドラーは呼び出されなくなります。Earlier we said that setting Handled to true prevents most handlers from being called. ただし、AddHandler メソッドを活用すると、ルート内の他のハンドラーが共有イベント データで Handledtrue に設定していても、ルートに対して必ず呼び出されるハンドラーをアタッチできます。But the AddHandler method provides a technique where you can attach a handler that is always invoked for the route, even if some other handler earlier in the route has set Handled to true in the shared event data. この手法が役立つのは、使っているコントロールが内部の合成ロジックまたはコントロール固有のロジックでイベントを処理済みにするが、This technique is useful if a control you are using has handled the event in its internal compositing or for control-specific logic. コントロールのインスタンスまたはアプリの UI からそのイベントに応答する必要がある場合です。but you still want to respond to it from a control instance, or your app UI. ただし、この手法は Handled の用途と矛盾し、コントロールの本来の対話操作を中断させる可能性があるため、使う際は注意が必要です。But use this technique with caution, because it can contradict the purpose of Handled and possibly break a control's intended interactions.

AddHandler によるイベント処理を使えるのは、対応するルーティング イベント識別子を持つルーティング イベントだけです。これは、AddHandler メソッドの入力として、その識別子が必要なためです。Only the routed events that have a corresponding routed event identifier can use the AddHandler event handling technique, because the identifier is a required input of the AddHandler method. ルーティング イベント識別子を使用可能にするイベントの一覧については、AddHandler のリファレンス ドキュメントをご覧ください。See the reference documentation for AddHandler for a list of events that have routed event identifiers available. ほとんどの部分は、ここまでに示したルーティング イベントの一覧と同じです。For the most part this is the same list of routed events we showed you earlier. 例外の一覧で最後の 2 つです。GotFocus LostFocus ルーティング イベント識別子、いないを使用することはできませんAddHandlerにとって。The exception is that the last two in the list: GotFocus and LostFocus don't have a routed event identifier, so you can't use AddHandler for those.

ビジュアル ツリー外のルーティング イベントRouted events outside the visual tree

一部のオブジェクトは、プライマリ ビジュアル ツリー (概念的にはメイン ビジュアル上のオーバーレイのようなもの) と関係しています。Certain objects participate in a relationship with the primary visual tree that is conceptually like having an overlay over the main visuals. このようなオブジェクトは、すべてのツリー要素と表示ルートを関連付ける通常の親子関係には含まれません。These objects are not part of the usual parent-child relationships that connect all tree elements to the visual root. たとえば、表示される PopupToolTip などがこれに該当します。This is the case for any displayed Popup or ToolTip. Popup または ToolTip からのルーティング イベントを処理する場合は、Popup 要素または ToolTip 要素そのものではなく、Popup または ToolTip 内の特定の UI 要素にハンドラーを配置してください。If you want to handle routed events from a Popup or ToolTip, place the handlers on specific UI elements that are within the Popup or ToolTip and not the Popup or ToolTip elements themselves. Popup または ToolTip のコンテンツに対して実行される合成の内部のルーティングには依存しないようにする必要があります。Don't rely on routing inside any compositing that is performed for Popup or ToolTip content. ルーティング イベントのイベント ルーティングは、メイン ビジュアル ツリーに沿った形でしか機能しないためです。This is because event routing for routed events works only along the main visual tree. PopupToolTip も、従属する UI 要素の親とは見なされず、(たとえば、Popup の既定の背景を入力イベントのキャプチャ領域として使用しようとしても) ルーティング イベントを受け取ることはできません。A Popup or ToolTip is not considered a parent of subsidiary UI elements and never receives the routed event, even if it is trying to use something like the Popup default background as the capture area for input events.

ヒット テストと入力イベントHit testing and input events

ある要素が、UI でマウス入力、タッチ入力、スタイラス入力の対象として表示されるかどうかと場所を確認することを、ヒット テストと呼びます。Determining whether and where in UI an element is visible to mouse, touch, and stylus input is called hit testing. タッチ操作や、タッチ操作の結果に発生する対話/操作イベントについては、ヒット テストで要素が表示されない場合、イベント ソースとして使用したり、操作に関連付けられたイベントを起動することはできません。For touch actions and also for interaction-specific or manipulation events that are consequences of a touch action, an element must be hit-test visible in order to be the event source and fire the event that is associated with the action. それ以外の場合、操作はその要素を通過し、その入力を操作する基になる要素またはビジュアル ツリー内の親要素へと渡されます。Otherwise, the action passes through the element to any underlying elements or parent elements in the visual tree that could interact with that input. ヒット テストに影響を与える要因はいくつかありますが、指定された要素の IsHitTestVisible プロパティを確認すると、その要素が入力イベントを発生できるかどうかを判別できます。There are several factors that affect hit testing, but you can determine whether a given element can fire input events by checking its IsHitTestVisible property. このプロパティは、要素が次の条件を満たす場合にのみ、true を返します。This property returns true only if the element meets these criteria:

  • 要素の Visibility プロパティの値が Visible である。The element's Visibility property value is Visible.
  • 要素の Background または Fill プロパティの値が null ではない。The element's Background or Fill property value is not null. A null ブラシ透過性で結果を値し、ヒット テストの非表示します。A null Brush value results in transparency and hit test invisibility. (要素を透明にしつつ、ヒット テストも可能にするには、null ではなく Transparent を使います)。(To make an element transparent but also hit testable, use a Transparent brush instead of null.)

  BackgroundFillUIElement では定義されません。ControlShape などの別の派生クラスによって定義されます。Note  Background and Fill aren't defined by UIElement, and are instead defined by different derived classes such as Control and Shape. ただし、フォアグラウンドやバックグラウンド プロパティに使用するブラシの影響は、それらのプロパティをどのサブクラスが実装するかに関係なく、ヒット テストや入力イベントに対して同様です。But the implications of brushes you use for foreground and background properties are the same for hit testing and input events, no matter which subclass implements the properties.

  • 要素がコントロールの場合、IsEnabled プロパティの値は true である必要がある。If the element is a control, its IsEnabled property value must be true.
  • 要素はレイアウトで実際のサイズを持ったものである必要がある。The element must have actual dimensions in layout. ActualHeightActualWidth のいずれかが 0 である要素は、入力イベントを発生させません。An element where either ActualHeight and ActualWidth are 0 won't fire input events.

一部のコントロールでは、ヒット テストに特別な規則があります。Some controls have special rules for hit testing. たとえば、TextBlock には Background プロパティがありませんが、そのサイズの領域全体の中ではヒット テストできます。For example, TextBlock has no Background property, but is still hit testable within the entire region of its dimensions. イメージ MediaElement コントロールが、メディアでアルファ チャネルなどの透過的なコンテンツに関係なく、四角形が定義されているディメンションでテスト可能なヒット表示されているソース ファイルです。Image and MediaElement controls are hit testable over their defined rectangle dimensions, regardless of transparent content such as alpha channel in the media source file being displayed. WebView コントロールがある特別なヒットがホスト型の HTML および火災スクリプト イベントで、入力を処理できるため、動作をテストします。WebView controls have special hit testing behavior because the input can be handled by the hosted HTML and fire script events.

ほとんどの Panel クラスと Border は、自身のバックグラウンド内ではヒット テストできませんが、含んでいる要素からルーティングされたユーザー入力イベントを処理することはできます。Most Panel classes and Border are not hit-testable in their own background, but can still handle the user input events that are routed from the elements that they contain.

要素がヒット テストできるかどうかにかかわらず、どの要素がユーザー入力イベントと同じ位置にあるかどうかを判別することができます。You can determine which elements are located at the same position as a user input event, regardless of whether the elements are hit-testable. そのためには、FindElementsInHostCoordinates メソッドを呼び出します。To do this, call the FindElementsInHostCoordinates method. このメソッドは名前のとおり、指定されたホスト要素からの相対的な位置にある要素を見つけます。As the name implies, this method finds the elements at a location relative to a specified host element. ただし、適用された変換やレイアウト変更により要素の相対座標系が調整されて、指定された場所でどの要素が見つかるかに影響する場合があります。However, applied transforms and layout changes can adjust the relative coordinate system of an element, and therefore affect which elements are found at a given location.

コマンド実行Commanding

コマンド実行がサポートされる UI 要素は少数です。A small number of UI elements support commanding. コマンド実行では、基になる実装で入力関連のルーティング イベントを使用し、1 つのコマンド ハンドラーを呼び出して関連する UI 入力 (特定のポインター操作、特定のショートカット キー) の処理を有効にします。Commanding uses input-related routed events in its underlying implementation and enables processing of related UI input (a certain pointer action, a specific accelerator key) by invoking a single command handler. UI 要素でコマンド実行を使うことができる場合は、個々の入力イベントではなく、コマンド実行 API を使うことを検討してください。If commanding is available for a UI element, consider using its commanding APIs instead of any discrete input events. 通常は Binding を使って、データのビュー モデルを定義するクラスのプロパティを参照します。You typically use a Binding reference into properties of a class that defines the view model for data. それらのプロパティに対応する名前付きコマンドで、言語固有の ICommand コマンド実行パターンを実装します。The properties hold named commands that implement the language-specific ICommand commanding pattern. 詳しくは、「ButtonBase.Command」をご覧ください。For more info, see ButtonBase.Command.

Windows ランタイムでのカスタム イベントCustom events in the Windows Runtime

カスタム イベントを定義するにあたっては、使われるプログラミング言語に応じて、イベントの追加方法や、それがクラスの設計でどのような意味を帯びるのかが大きく異なります。For purposes of defining custom events, how you add the event and what that means for your class design is highly dependent on which programming language you are using.

  • C# と Visual Basic では、CLR のイベントを定義します。For C# and Visual Basic, you are defining a CLR event. カスタム アクセサー (add/remove) を使っていない限り、標準の .NET イベントのパターンを使うことができます。You can use the standard .NET event pattern, so long as you aren't using custom accessors (add/remove). 次の点にも注意してください。Additional tips:
  • C++/CX については、「イベント (C++/CX)」をご覧ください。For C++/CX, see Events (C++/CX).
    • カスタム イベントを自ら使う場合であっても、名前付き参照を使ってください。Use named references even for your own usages of custom events. カスタム イベントにラムダは使えません。ラムダを使うと、循環参照が作られることになります。Don't use lambda for custom events, it can create a circular reference.

Windows ランタイムでカスタム ルーティング イベントは宣言できません。ルーティング イベントは、Windows ランタイムのセットに限定されます。You can't declare a custom routed event for Windows Runtime; routed events are limited to the set that comes from the Windows Runtime.

カスタム イベントの定義は通常、カスタム コントロールを定義する一環として実行されます。Defining a custom event is usually done as part of the exercise of defining a custom control. プロパティ変更コールバックのある依存関係プロパティだけでなく、その依存関係プロパティのコールバックで (必ずまたはときどき) 発生するカスタム イベントを定義するのがよくあるパターンです。It's a common pattern to have a dependency property that has a property-changed callback, and to also define a custom event that's fired by the dependency property callback in some or all cases. コントロールのユーザーには定義したプロパティ変更コールバックに対するアクセス権がないものの、通知イベントは利用可能にするというのが次善策です。Consumers of your control don't have access to the property-changed callback you defined, but having a notification event available is the next best thing. 詳しくは、「カスタム依存関係プロパティ」をご覧ください。For more info, see Custom dependency properties.