ルーティング イベントの処理済みとしてのマーキング、およびクラス処理Marking Routed Events as Handled, and Class Handling

ルーティング イベントのハンドラーでは、イベント データ内で、イベントを処理済みとしてマークできます。Handlers for a routed event can mark the event handled within the event data. イベントを処理すると、ルートが事実上短縮されます。Handling the event will effectively shorten the route. クラス処理は、ルーティング イベントでサポートされているプログラミング概念です。Class handling is a programming concept that is supported by routed events. クラス ハンドラーでは、特定のルーティング イベントをクラス レベルのハンドラーで処理することができます。このハンドラーは、そのクラスのどのインスタンスのどのインスタンス ハンドラーよりも先に呼び出されます。A class handler has the opportunity to handle a particular routed event at a class level with a handler that is invoked before any instance handler on any instance of the class.

必須コンポーネントPrerequisites

このトピックでは、「ルーティング イベントの概要」で紹介した概念を詳しく説明します。This topic elaborates on concepts introduced in the Routed Events Overview.

イベントを処理済みとしてマークする場合When to Mark Events as Handled

値を設定すると、Handledプロパティをtrueイベントのルーティング イベントのデータと呼ばれるを「イベントを処理済みのマークを付ける」。When you set the value of the Handled property to true in the event data for a routed event, this is referred to as "marking the event handled". アプリケーションの作成者や、既存のルーティング イベントへの応答や新しいルーティング イベントの実装を行うコントロールの作成者が、どのような場合にルーティング イベントを処理済みとしてマークするかについては、絶対的な規則はありません。There is no absolute rule for when you should mark routed events as handled, either as an application author, or as a control author who responds to existing routed events or implements new routed events. ほとんどの場合、ルーティング イベントのイベント データで運ばれる "処理済み" の概念は、WPFWPF APIAPIs で公開されているさまざまなルーティング イベントやカスタム ルーティング イベントに対するアプリケーションの応答のために、限定的なプロトコルとして使用する必要があります。For the most part, the concept of "handled" as carried in the routed event's event data should be used as a limited protocol for your own application's responses to the various routed events exposed in WPFWPF APIAPIs as well as for any custom routed events. また、"処理済み" の問題のもう 1 つの考え方があります。ルーティング イベントに対するコードの応答が重要かつ比較的完全な形で行われた場合は、一般にルーティング イベントを処理済みとしてマークする必要があります。Another way to consider the "handled" issue is that you should generally mark a routed event handled if your code responded to the routed event in a significant and relatively complete way. 通常は、1 つのルーティング イベント発生に対して、異なるハンドラー実装を必要とする複数の重要な応答があることは好ましくありません。Typically, there should not be more than one significant response that requires separate handler implementations for any single routed event occurrence. 複数の応答が必要な場合は、ルーティング イベント システムを使用して転送するのではなく、単一のハンドラー内で一連のアプリケーション ロジックとして必要なコードを実装する必要があります。If more responses are needed, then the necessary code should be implemented through application logic that is chained within a single handler rather than by using the routed event system for forwarding. また、何が "重要" と考えるかも主観的なもので、アプリケーションやコードに応じて異なります。The concept of what is "significant" is also subjective, and depends on your application or code. 一般的に、"重要な応答" の例には、フォーカスの設定、パブリック状態の変更、ビジュアル表現に影響するプロパティの設定、他の新しいイベントの発生などがあります。As general guidance, some "significant response" examples include: setting focus, modifying public state, setting properties that affect the visual representation, and raising other new events. 重要でない応答の例には、プライベート状態の変更 (ビジュアル表現への影響やプログラムによる表現を伴わない変更) や、イベントのログなどがあります。イベントの引数を確認して応答しないように選択する場合もこれに含まれます。Examples of nonsignificant responses include: modifying private state (with no visual impact, or programmatic representation), logging of events, or looking at arguments of an event and choosing not to respond to it.

ハンドラーが追加されるため、ルーティング イベント システムの動作は、ルーティング イベントの処理済みの状態を使用するためには、この「重要な応答」モデルを補強XAMLXAMLまたはの一般的なシグネチャAddHandlerルーティング イベントに対しては呼び出されません、イベントデータは、既に処理済みでマークされます。The routed event system behavior reinforces this "significant response" model for using handled state of a routed event, because handlers added in XAMLXAML or the common signature of AddHandler are not invoked in response to a routed event where the event data is already marked handled. ハンドラーを追加するという作業を進める必要があります、handledEventsTooパラメーター バージョン (AddHandler(RoutedEvent, Delegate, Boolean)) 以前の参加者によって処理済みとマークされているルーティング イベントのイベントのルーティングを処理するためにします。You must go through the extra effort of adding a handler with the handledEventsToo parameter version (AddHandler(RoutedEvent, Delegate, Boolean)) in order to handle routed events that are marked handled by earlier participants in the event route.

場合によっては、コントロール自体が特定のルーティング イベントを処理済みとしてマークすることもあります。In some circumstances, controls themselves mark certain routed events as handled. ルーティング イベントが処理済みとマークされた場合、ルーティング イベントへの応答としてコントロールが行ったアクションは、コントロールの実装の一部として重要、完全なもので、そのイベントにはそれ以上の処理は必要ないと、WPFWPF コントロールの作成者が判断したことを表しています。A handled routed event represents a decision by WPFWPF control authors that the control's actions in response to the routed event are significant or complete as part of the control implementation, and the event needs no further handling. これは通常、イベントのクラス ハンドラーを追加するか、基底クラスに存在するクラス ハンドラー仮想メソッドの 1 つをオーバーライドすることによって行われます。Usually this is done by adding a class handler for an event, or by overriding one of the class handler virtuals that exist on a base class. このイベント処理は、必要に応じて回避することもできます。詳細については、このトピックの「コントロールによるイベント抑制の回避」をご覧ください。You can still work around this event handling if necessary; see Working Around Event Suppression by Controls later in this topic.

"プレビュー" (トンネル) イベントとバブル イベントのイベント処理"Preview" (Tunneling) Events vs. Bubbling Events, and Event Handling

プレビュー ルーティング イベントは、要素ツリーのトンネル ルートをたどるイベントです。Preview routed events are events that follow a tunneling route through the element tree. 名前付け規則に含まれる "Preview" は、対応するバブル ルーティング イベントより前にプレビュー (トンネル) ルーティング イベントが発生するという入力イベントの原則を表しています。The "Preview" expressed in the naming convention is indicative of the general principle for input events that preview (tunneling) routed events are raised prior to the equivalent bubbling routed event. また、トンネルとバブルのペアを持つ入力ルーティング イベントは、別個の処理ロジックを持ちます。Also, input routed events that have a tunneling and bubbling pair have a distinct handling logic. トンネル/プレビュー ルーティング イベントがイベント リスナーによって処理済みとしてマークされた場合、バブル ルーティング イベントは処理済みとしてマークされます。これは、バブル ルーティング イベントのすべてのリスナーがそのイベントを受け取る前であっても変わりません。If the tunneling/preview routed event is marked as handled by an event listener, then the bubbling routed event will be marked handled even before any listeners of the bubbling routed event receive it. トンネル ルーティング イベントとバブル ルーティング イベントは、厳密には別個のイベントですが、この動作を実現するために、同じイベント データのインスタンスをあえて共有しています。The tunneling and bubbling routed events are technically separate events, but they deliberately share the same instance of event data to enable this behavior.

このトンネル ルーティング イベントとバブル ルーティング イベントの間の関連は、任意の WPFWPF クラスで宣言されたルーティング イベントをそのクラスが発生させる方法の内部実装によって実現されます。これは入力ルーティング イベントのペアにも当てはまります。The connection between the tunneling and bubbling routed events is accomplished by the internal implementation of how any given WPFWPF class raises its own declared routed events, and this is true of the paired input routed events. このクラスレベルの実装が存在しなければ、名前付けスキームを共有するトンネル ルーティング イベントとバブル ルーティング イベントの間に関連はありません。つまり、そのような実装がなければ、それらは 2 つのまったく別のルーティング イベントとなり、順番に発生することや、イベント データを共有することはなくなります。But unless this class-level implementation exists, there is no connection between a tunneling routed event and a bubbling routed event that share the naming scheme: without such implementation they would be two entirely separate routed events and would not be raised in sequence or share event data.

カスタム クラスでトンネル/バブル入力ルーティング イベントのペアを実装する方法の詳細については、「方法 : カスタム ルーティング イベントを作成する」をご覧ください。For more information about how to implement tunnel/bubble input routed event pairs in a custom class, see Create a Custom Routed Event.

クラス ハンドラーとインスタンス ハンドラーClass Handlers and Instance Handlers

ルーティング イベントでは、クラス リスナーとインスタンス リスナーという 2 種類のイベント リスナーが考慮されます。Routed events consider two different types of listeners to the event: class listeners and instance listeners. 型の特定が呼び出されるために、クラス リスナーが存在してEventManager APIAPIRegisterClassHandler、静的コンス トラクターでまたは要素の基本クラスからクラス ハンドラー仮想メソッドをオーバーライドします。Class listeners exist because types have called a particular EventManager APIAPI ,RegisterClassHandler, in their static constructor, or have overridden a class handler virtual method from an element base class. インスタンス リスナーが特定のクラス インスタンス/要素を 1 つまたは複数のハンドラーがアタッチされたルーティング イベントへの呼び出しによってAddHandlerします。Instance listeners are particular class instances/elements where one or more handlers have been attached for that routed event by a call to AddHandler. 既存のWPFWPFルーティング イベントは、呼び出しを行うAddHandlerの一部として、共通言語ランタイム (CLR)common language runtime (CLR)イベント ラッパーの追加{}および削除{}も方法は、イベントの実装、単純なXAMLXAMLアタッチのメカニズム属性構文を使用してイベント ハンドラーが有効になっているとします。Existing WPFWPF routed events make calls to AddHandler as part of the 共通言語ランタイム (CLR)common language runtime (CLR) event wrapper add{} and remove{} implementations of the event, which is also how the simple XAMLXAML mechanism of attaching event handlers via an attribute syntax is enabled. そのため、単純なであってもXAMLXAML使用量は、最終的に相当、AddHandler呼び出します。Therefore even the simple XAMLXAML usage ultimately equates to an AddHandler call.

登録されたハンドラー実装があるかどうか、ビジュアル ツリー内の各要素がチェックされます。Elements within the visual tree are checked for registered handler implementations. ハンドラーはルート全体で呼び出される可能性があり、呼び出される順序は、ルーティング イベントのルーティング戦略によってあらかじめ決まっています。Handlers are potentially invoked throughout the route, in the order that is inherent in the type of the routing strategy for that routed event. たとえば、バブル ルーティング イベントでは、ルーティング イベントを発生させた要素と同じ要素にアタッチされているハンドラーが最初に呼び出されます。For instance, bubbling routed events will first invoke those handlers that are attached to the same element that raised the routed event. その後、ルーティング イベントは次の親要素に "浮上" します。アプリケーションのルート要素に到達するまで、これが繰り返されます。Then the routed event "bubbles" to the next parent element and so on until the application root element is reached.

バブル ルートのルート要素の視点から見ると、イベント引数を処理済みとしてマークするハンドラーが、クラス処理や、よりルーティング イベント ソースに近い要素によって呼び出された場合、ルート要素のハンドラーは呼び出されません。これにより、イベント ルートは、ルート要素に到達する前に事実上短縮されます。From the perspective of the root element in a bubbling route, if class handling or any element closer to the source of the routed event invoke handlers that mark the event arguments as being handled, then handlers on the root elements are not invoked, and the event route is effectively shortened before reaching that root element. しかし、イベント ルートが完全に停止するわけではありません。クラス ハンドラーやインスタンス ハンドラーによってルーティング イベントが処理済みとしてマークされた場合にも呼び出されるように、特別な条件を使用してハンドラーが追加されている可能性があるためです。However, the route is not completely halted, because handlers can be added using a special conditional that they should still be invoked, even if a class handler or instance handler has marked the routed event as handled. 詳細については、このトピックで後述する「イベントが処理済みとしてマークされていても呼び出されるインスタンス ハンドラーの追加」をご覧ください。This is explained in Adding Instance Handlers That Are Raised Even When Events Are Marked Handled, later in this topic.

イベント ルートより深いレベルでは、クラスの特定のインスタンスに対して、複数のクラス ハンドラーが作用している可能性もあります。At a deeper level than the event route, there are also potentially multiple class handlers acting on any given instance of a class. なぜなら、ルーティング イベントのクラス処理モデルでは、クラスの階層構造に属するすべてのクラスが、各ルーティング イベントに対して独自のクラス ハンドラーをそれぞれ登録できるためです。This is because the class handling model for routed events enables all possible classes in a class hierarchy to each register its own class handler for each routed event. 各クラス ハンドラーは内部ストアに追加され、アプリケーションのイベント ルートが構築されたときには、すべてのクラス ハンドラーがイベント ルートに追加されます。Each class handler is added to an internal store, and when the event route for an application is constructed, the class handlers are all added to the event route. クラス ハンドラーは、最派生クラスのクラス ハンドラーが最初に呼び出され、以下それぞれの基底クラスのクラス ハンドラーが順に呼び出されていくように、ルートに追加されます。Class handlers are added to the route such that the most-derived class handler is invoked first, and class handlers from each successive base class are invoked next. 一般に、クラス ハンドラーは、既に処理済みとしてマークされたルーティング イベントにも反応するようには登録されません。Generally, class handlers are not registered such that they also respond to routed events that were already marked handled. したがって、このクラス処理のしくみでは、次の 2 つの方法のいずれかを実現できます。Therefore, this class handling mechanism enables one of two choices:

  • 派生クラスでは、基底クラスから継承されたクラス処理を補完するために、ルーティング イベントを処理済みとしてマークしないハンドラーを追加することができます。これは、派生クラスのハンドラーより後に基底クラスのハンドラーが呼び出されるためです。Derived classes can supplement the class handling that is inherited from the base class by adding a handler that does not mark the routed event handled, because the base class handler will be invoked sometime after the derived class handler.

  • 派生クラスでは、ルーティング イベントを処理済みとしてマークするクラス ハンドラーを追加することで、基底クラスのクラス処理を置き換えることができます。Derived classes can replace the class handling from the base class by adding a class handler that marks the routed event handled. この方法を使用する場合には注意が必要です。外観、状態のロジック、入力処理、コマンド処理などの部分で、基底コントロールが意図した設計と変わってしまう可能性があります。You should be cautious with this approach, because it will potentially change the intended base control design in areas such as visual appearance, state logic, input handling, and command handling.

コントロールの基底クラスでのルーティング イベントのクラス処理Class Handling of Routed Events by Control Base Classes

イベント ルートの各要素ノードでは、クラス リスナーに、その要素のどのインスタンス リスナーよりも先にルーティング イベントに応答する機会が与えられます。On each given element node in an event route, class listeners have the opportunity to respond to the routed event before any instance listener on the element can. このため、特定のコントロール クラス実装でそれ以上伝達されないようにルーティング イベントを抑制したり、ルーティング イベントに対してそのクラスの機能である特別な処理を提供したりするために、クラス ハンドラーが使用されることもあります。For this reason, class handlers are sometimes used to suppress routed events that a particular control class implementation does not wish to propagate further, or to provide special handling of that routed event that is a feature of the class. たとえば、クラス固有の独自のイベントを発生させて、特定のクラスのコンテキストでユーザー入力の状態が持つ意味についてより具体的な情報をそのイベントに含めることができます。For instance, a class might raise its own class-specific event that contains more specifics about what some user input condition means in the context of that particular class. この場合、そのクラス実装によって、より一般的なルーティング イベントが処理済みとしてマークされます。The class implementation might then mark the more general routed event as handled. クラス ハンドラーは、通常、追加のルーティングが呼び出されないように、共有イベント データが既にマークされたイベントの処理が、特殊なケースがあります、RegisterClassHandler(Type, RoutedEvent, Delegate, Boolean)署名ルーティング イベントがいるときでもを呼び出すためのクラス ハンドラーを登録します。処理済みとしてマークします。Class handlers are typically added such that they are not invoked for routed events where shared event data was already marked handled, but for atypical cases there is also a RegisterClassHandler(Type, RoutedEvent, Delegate, Boolean) signature that registers class handlers to invoke even when routed events are marked handled.

クラス ハンドラー仮想メソッドClass Handler Virtuals

一部の要素に、基本要素など、特にUIElement、公開空"の * イベント"と"OnPreview*イベント"パブリック ルーティング イベントの一覧に対応する仮想メソッド。Some elements, particularly the base elements such as UIElement, expose empty "On*Event" and "OnPreview*Event" virtual methods that correspond to their list of public routed events. これらの仮想メソッドをオーバーライドすれば、そのルーティング イベントに対するクラス ハンドラーを実装することができます。These virtual methods can be overridden to implement a class handler for that routed event. 基本要素クラスのこれらの各クラス ハンドラーを使用してイベント ルーティングされるため、これらの仮想メソッドを登録するRegisterClassHandler(Type, RoutedEvent, Delegate, Boolean)前述のとおりです。The base element classes register these virtual methods as their class handler for each such routed event using RegisterClassHandler(Type, RoutedEvent, Delegate, Boolean) as described earlier. On*Event 仮想メソッドを使用すると、対応するルーティング イベントのクラス処理の実装が大幅に簡略化され、それぞれの型の静的コンストラクターで特別な初期化を行う必要がなくなります。The On*Event virtual methods make it much simpler to implement class handling for the relevant routed events, without requiring special initialization in static constructors for each type. クラス処理を追加するなど、DragEnterいずれかでイベントUIElement派生クラスをオーバーライドすることで、OnDragEnter仮想メソッド。For instance, you can add class handling for the DragEnter event in any UIElement derived class by overriding the OnDragEnter virtual method. オーバーライドの中では、ルーティング イベントを処理する、他のイベントを発生させる、インスタンスの要素プロパティを変更する可能性があるクラス固有のロジックを開始するなどのアクションや、これらのアクションの任意の組み合わせを実行できます。Within the override, you could handle the routed event, raise other events, initiate class-specific logic that might change element properties on instances, or any combination of those actions. 一般に、こうしたオーバーライドでは、イベントを処理済みとしてマークする場合でも、基本実装を呼び出す必要があります。You should generally call the base implementation in such overrides even if you mark the event handled. これらの仮想メソッドは基底クラスで定義されているため、基本実装を呼び出すことを強くお勧めします。Calling the base implementation is strongly recommended because the virtual method is on the base class. プロテクト仮想メソッドの標準的な呼び出しパターンでは、それぞれの仮想メソッドから、基本実装を呼び出す形になります。これは、ルーティング イベントのクラス処理の固有のしくみ (任意のインスタンスに対して、最派生クラスのハンドラーから基底クラスのハンドラーへという順で、クラス階層構造のすべてのクラスのクラス ハンドラーが呼び出される) を実質的に置き換え、同様の処理を実現することになります。The standard protected virtual pattern of calling the base implementations from each virtual essentially replaces and parallels a similar mechanism that is native to routed event class handling, whereby class handlers for all classes in a class hierarchy are called on any given instance, starting with the most-derived class' handler and continuing to the base class handler. 基本実装の呼び出しを省略するのは、基底クラスの処理ロジックを意図的に変更する必要がある場合だけにしてください。You should only omit the base implementation call if your class has a deliberate requirement to change the base class handling logic. 基本実装をオーバーライド コードの前と後のどちらで呼び出すかは、それぞれの実装の性質によって異なります。Whether you call the base implementation before or after your overriding code will depend on the nature of your implementation.

入力イベント クラスの処理Input Event Class Handling

すべてのクラス ハンドラー仮想メソッドは、すべての共有イベント データが処理済みとしてマークされていない場合にのみ呼び出されるように登録されます。The class handler virtual methods are all registered such that they are only invoked in cases where any shared event data are not already marked handled. また、入力イベントに固有のしくみとして、一般に、トンネル バージョンとバブル バージョンのイベントが順番に発生し、両方のバージョンでイベント データが共有されます。Also, for the input events uniquely, the tunneling and bubbling versions typically are raised in sequence and share event data. このため、トンネル バージョンとバブル バージョンの入力イベント用のクラス ハンドラーの特定のペアについて、イベントがすぐに処理済みとしてマークされないようにしたい場合があります。This entails that for a given pair of class handlers of input events where one is the tunneling version and the other is the bubbling version, you may not want to mark the event handled immediately. イベントを処理済みとしてマークするようにトンネル クラス処理の仮想メソッドを実装すると、バブル クラスのハンドラーが呼び出されなくなります (トンネル イベントやバブル イベントに対して通常の方法で登録したインスタンス ハンドラーも呼び出されません)。If you implement the tunneling class handling virtual method to mark the event handled, that will prevent the bubbling class handler from being invoked (as well as preventing any normally registered instance handlers for either the tunneling or bubbling event from being invoked).

ノードでのクラス処理が完了すると、インスタンス リスナーが考慮されます。Once class handling on a node is complete, the instance listeners are considered.

イベントが処理済みとしてマークされていても呼び出されるインスタンス ハンドラーの追加Adding Instance Handlers That Are Raised Even When Events Are Marked Handled

AddHandlerメソッドが呼び出されるイベント システムによってイベントがルートの処理中の要素に達するたびをマークするイベント データを他のハンドラーが既に調整されている場合でもハンドラーを追加することを許可する特定のオーバー ロードを提供イベントを処理します。The AddHandler method supplies a particular overload that allows you to add handlers that will be invoked by the event system whenever an event reaches the handling element in the route, even if some other handler has already adjusted the event data to mark that event as handled. この方法は通常は使用されません。This is not typically done. 一般にハンドラーは、イベントが要素ツリーのどこで処理されるかに関係なく、そのイベントによって影響を受ける可能性があるアプリケーション コードのすべての領域を調整するように作成することができます。これは、複数の結果が求められる場合でも同じです。Generally, handlers can be written to adjust all areas of application code that might be influenced by an event, regardless of where it was handled in an element tree, even if multiple end results are desired. また、通常は、そのイベントに応答する必要がある要素は実際に 1 つだけなので、適切なアプリケーション ロジックが既に発生していることになります。Also, typically there is really only one element that needs to respond to that event, and the appropriate application logic had already happened. しかし、イベントが要素ツリーやコントロール複合の他の要素によって既に処理済みとしてマークされていても、要素ツリーのもっと上 (ルートによってはもっと下) にある他の要素のハンドラーを呼び出す必要がある場合もあります。そうした例外的なケースに対しては、handledEventsToo オーバーロードを使用することができます。But the handledEventsToo overload is available for the exceptional cases where some other element in an element tree or control compositing has already marked an event as handled, but other elements either higher or lower in the element tree (depending on route) still wish to have their own handlers invoked.

処理済みのイベントを未処理としてマークする場合When to Mark Handled Events as Unhandled

一般に、処理済みとマークされているルーティング イベント マークしないでハンドルされていない (Handled戻してfalse) で動作するハンドラーによってもhandledEventsTooします。Generally, routed events that are marked handled should not be marked unhandled (Handled set back to false) even by handlers that act on handledEventsToo. しかし、一部の入力イベントでは、高レベルのイベント表現と低レベルのイベント表現が重複することがあります。ツリー内のある位置では高レベルのイベントが取得され、別の位置では低レベルのイベントが取得される場合です。However, some input events have high-level and lower-level event representations that can overlap when the high-level event is seen at one position in the tree and the low-level event at another position. たとえば、高度なキー イベントで子要素をリッスンなどを検討TextInputなど、親要素が低レベルのイベントを待機中にKeyDownします。For instance, consider the case where a child element listens to a high-level key event such as TextInput while a parent element listens to a low-level event such as KeyDown. 親要素が低レベルのイベントを処理した場合、直感的には子要素が先にイベントを処理するはずであるにもかかわらず、高レベルのイベントが子要素で抑制されてしまうことがあります。If the parent element handles the low-level event, the higher-level event can be suppressed even in the child element that intuitively should have first opportunity to handle the event.

このような状況では、親要素と子要素の両方に低レベルのイベントのハンドラーを追加する必要があります。In these situations it may be necessary to add handlers to both parent elements and child elements for the low-level event. この場合、子要素のハンドラー実装によって低レベルのイベントが処理済みとしてマークされる可能性がありますが、親要素のハンドラー実装がそれを再び未処理に設定して、ツリーのもっと上にある要素 (および高レベルのイベント) がそのイベントに応答できるようにします。The child element handler implementation can mark the low-level event as handled, but the parent element handler implementation would set it unhandled again so that further elements up the tree (as well as the high-level event) can have the opportunity to respond. この状況は通常はあまりありません。This situation is should be fairly rare.

コントロール複合の入力イベントの意図的な抑制Deliberately Suppressing Input Events for Control Compositing

ルーティング イベントのクラス処理は、主に入力イベントと複合コントロールに対して使用されます。The main scenario where class handling of routed events is used is for input events and composited controls. 複合コントロールは、その名のとおり、複数の実用的なコントロールまたはコントロールの基底クラスで構成されています。A composited control is by definition composed of multiple practical controls or control base classes. コントロールを作成する際に、それらの各サブコンポーネントで発生するすべての入力イベントを 1 つにまとめて、コントロール全体が 1 つのイベント ソースとしてイベントを報告するように作る場合があります。Often the author of the control wishes to amalgamate all of the possible input events that each of the subcomponents might raise, in order to report the entire control as the singular event source. また、コンポーネントからのイベントを完全に抑制する場合や、コンポーネントで定義された別のイベント (より多くの情報を含むイベントや、より具体的な動作を表すイベント) に置き換える場合もあります。In some cases the control author might wish to suppress the events from components entirely, or substitute a component-defined event that carries more information or implies a more specific behavior. コンポーネント作成者はすぐに表示されている標準的な例は、方法、 Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) Buttonのすべてのボタンのある直感的なイベントを解決する最終的に任意のマウス イベントの処理:Clickイベント。The canonical example that is immediately visible to any component author is how a Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) Button handles any mouse event that will eventually resolve to the intuitive event that all buttons have: a Click event.

Button基底クラス (ButtonBase) から派生したControlから派生した順番FrameworkElementUIElement、コントロールの入力の処理は、必要なイベント インフラストラクチャの大半、UIElementレベル。The Button base class (ButtonBase) derives from Control which in turn derives from FrameworkElement and UIElement, and much of the event infrastructure needed for control input processing is available at the UIElement level. 具体的には、UIElement全般処理Mouse ボタン、アクションをなど、その境界内でマウス カーソルのヒット テストを処理し、最も一般的なに対する個別のイベントを提供するイベントMouseLeftButtonDownします。In particular, UIElement processes general Mouse events that handle hit testing for the mouse cursor within its bounds, and provides distinct events for the most common button actions, such as MouseLeftButtonDown. UIElement 仮想、空にも提供OnMouseLeftButtonDownの登録済みクラス ハンドラーとしてMouseLeftButtonDown、およびButtonBaseをオーバーライドします。UIElement also provides an empty virtual OnMouseLeftButtonDown as the preregistered class handler for MouseLeftButtonDown, and ButtonBase overrides it. 同様に、ButtonBaseはクラスのハンドラーMouseLeftButtonUpします。Similarly, ButtonBase uses class handlers for MouseLeftButtonUp. イベント データに渡される、上書き、実装をマークするRoutedEventArgsインスタンスを設定して処理済みとしてHandledtrue、および同じイベント データがどのような継続するその他のクラス ハンドラーへのルートの残りの部分とインスタンス ハンドラーや、イベント setter にもIn the overrides, which are passed the event data, the implementations mark that RoutedEventArgs instance as handled by setting Handled to true, and that same event data is what continues along the remainder of the route to other class handlers and also to instance handlers or event setters. また、OnMouseLeftButtonUpオーバーライドを次に発生させる、Clickイベント。Also, the OnMouseLeftButtonUp override will next raise the Click event. ほとんどのリスナーの最終結果になります、MouseLeftButtonDownMouseLeftButtonUpイベントが「消滅」し代わりに置き換えられますClick、ことがわかっているのでこのイベントの発生元を本当のボタンとその一部ではないからより多くの意味を保持するイベント複合はピース全体またはその他の要素から、ボタンのです。The end result for most listeners will be that the MouseLeftButtonDown and MouseLeftButtonUp events "disappear" and are replaced instead by Click, an event that holds more meaning because it is known that this event originated from a true button and not some composite piece of the button or from some other element entirely.

コントロールによるイベント抑制の回避Working Around Event Suppression by Controls

個々のコントロール内で行われるこのイベントの抑制の動作が、アプリケーションのイベント処理ロジックの全体的な目的の妨げになることがあります。Sometimes this event suppression behavior within individual controls can interfere with some more general intentions of event handling logic for your application. たとえば、何らかの理由のかどうかと、アプリケーションがハンドラーをMouseLeftButtonDownアプリケーションのルート要素にある、<xref:system.windows.uielement.mouseleftbuttondown> のボタンをマウスでクリックは呼び出しませんMouseLeftButtonDownまたはMouseLeftButtonUpルート レベルのハンドラー。For instance, if for some reason your application had a handler for MouseLeftButtonDown located at the application root element, you would notice that any mouse click on a button would not invoke MouseLeftButtonDown or MouseLeftButtonUp handlers at the root level. イベント自体は実際に "浮上" しました (既に説明したように、処理済みとしてマークされた後、イベント ルートは終了するのではなく、ルーティング イベント システムによってハンドラー呼び出しの動作が変更されます)。The event itself actually did bubble up (again, event routes are not truly ended, but the routed event system changes their handler invocation behavior after being marked handled). ルーティング イベントに達すると、ボタン、ButtonBaseクラス処理がマークされている、MouseLeftButtonDownを置き換えるためにの処理、Click詳細の意味を持つイベント。When the routed event reached the button, the ButtonBase class handling marked the MouseLeftButtonDown handled because it wished to substitute the Click event with more meaning. そのため、任意の標準MouseLeftButtonDownへのルート ハンドラーをさらには呼び出されなくなります。Therefore, any standard MouseLeftButtonDown handler further up the route would not be invoked. このような状況でもハンドラーが呼び出されるようにするには 2 つの方法があります。There are two techniques you can use to ensure that your handlers would be invoked in this circumstance.

最初の手法がハンドラーを使用して、意図的に追加するには、handledEventsTooのシグネチャAddHandler(RoutedEvent, Delegate, Boolean)します。The first technique is to deliberately add the handler using the handledEventsToo signature of AddHandler(RoutedEvent, Delegate, Boolean). この方法には、イベント ハンドラーの追加をコードからしか行えず、マークアップからは行うことができないという制限があります。A limitation of this approach is that this technique for attaching an event handler is only possible from code, not from markup. Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML) でイベント属性の値としてイベント ハンドラー名を指定する単純な構文では、この動作は実現できません。The simple syntax of specifying the event handler name as an event attribute value via Extensible Application Markup Language (XAML)Extensible Application Markup Language (XAML) does not enable that behavior.

2 つ目の方法は、トンネル バージョンとバブル バージョンのルーティング イベントがペアになっている入力イベントでのみ使用できます。The second technique works only for input events, where the tunneling and bubbling versions of the routed event are paired. これらのルーティング イベントについて、対応するプレビュー/トンネル ルーティング イベントにハンドラーを追加することができます。For these routed events, you can add handlers to the preview/tunneling equivalent routed event instead. そのルーティング イベントはルートからトンネリングを開始するため、アプリケーション要素ツリーの先祖要素のレベルにプレビュー ハンドラーをアタッチしておけば、イベントがボタン クラス処理コードによってインターセプトされなくなります。That routed event will tunnel through the route starting from the root, so the button class handling code would not intercept it, presuming that you attached the Preview handler at some ancestor element level in the application's element tree. この方法を使用する場合は、プレビュー イベントを処理済みとしてマークする際に注意が必要です。If you use this approach, be cautious about marking any Preview event handled. 指定の例のPreviewMouseLeftButtonDownとしてイベントをマークされている場合、ルート要素で処理されるHandledハンドラーの実装では実際に抑制する、Clickイベント。For the example given with PreviewMouseLeftButtonDown being handled at the root element, if you marked the event as Handled in the handler implementation, you would actually suppress the Click event. 通常これは望ましくない動作です。That is typically not desirable behavior.

関連項目See also