라우트된 이벤트를 처리된 것으로 표시 및 클래스 처리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. 대부분의 경우 라우트된 이벤트의 이벤트 데이터에서 수행 되는 "처리 됨" 개념은 api에 WPFWPF 노출 되는 다양 한 라우트된 이벤트 뿐만 아니라 사용자 지정 라우트된 이벤트에 대 한 자체 응용 프로그램의 응답에 대 한 제한 된 프로토콜로 사용 해야 합니다.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 APIs as well as for any custom routed events. “처리됨” 문제로 간주하는 또 다른 방법은 일반적으로 코드에서 의미 있고 비교적 완전한 방법으로 라우트된 이벤트에 응답한 경우 라우트된 이벤트를 처리된 것으로 표시하는 것입니다.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. 일반적으로 라우트된 이벤트 하나가 발생할 때마다 별도의 처리기를 구현해야 하는 의미 있는 응답은 하나만 있어야 합니다.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. 이 경우에는 대개 이벤트에 대한 클래스 처리기를 추가하거나 기본 클래스에 존재하는 클래스 처리기 가상 메서드 중 하나를 재정의하게 됩니다.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. 명명 규칙에서 표현된 “미리 보기”는 라우트된 미리 보기(터널링) 이벤트가 그에 해당되는 라우트된 버블링 이벤트보다 먼저 발생한다는 입력 이벤트의 일반적인 원칙을 나타냅니다.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. 하지만 이 클래스 수준 구현이 존재하지 않으면 라우트된 터널링 이벤트와 라우트된 버블링 이벤트 간에 이름 지정 체계를 공유하는 연결이 없습니다. 이와 같은 구현이 없으면 이 두 이벤트는 완전히 분리된 두 개의 라우트된 이벤트이며 차례로 발생하거나 이벤트 데이터를 공유하지 않습니다.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

라우트된 이벤트에서는 클래스 수신기와 인스턴스 수신기라는 두 가지 종류의 이벤트 수신기를 사용합니다.Routed events consider two different types of listeners to the event: class listeners and instance listeners. 클래스 수신기는 형식이 특정 EventManager API,RegisterClassHandler를 정적 생성자에서 호출 했거나 요소 기본 클래스에서 클래스 처리기 가상 메서드를 재정의 했기 때문에 존재 합니다.Class listeners exist because types have called a particular EventManager API ,RegisterClassHandler, in their static constructor, or have overridden a class handler virtual method from an element base class. 인스턴스 수신기는를 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 (공용 언어 런타임) 이벤트 래퍼의 일부로 호출{} 하 고{} , XAMLXAML 이벤트의 구현을 추가 및 제거 합니다. 특성 구문을 통해 이벤트 처리기를 연결할 수 있습니다.Existing WPFWPF routed events make calls to AddHandler as part of the 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. 따라서 이 클래스 처리 메커니즘을 사용할 경우 다음 두 가지 중 하나를 선택할 수 있습니다.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같은 기본 요소는 공용 라우트된 이벤트 목록에 해당 하는 빈 "On * event" 및 "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 OnDragEnter 가상 메서드를 재정의 하 여 UIElement 파생 클래스에서 이벤트에 대 한 클래스 처리를 추가할 수 있습니다.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. 또한 특정 이벤트에 응답해야 하는 요소가 실제로 하나인 경우가 많으며 적절한 애플리케이션 논리가 이미 있는 경우가 많습니다.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 handledEventsToo작동 하는 처리기에 false의해 처리 되지 않은 (다시 설정)로 표시 되어서는 안 됩니다.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. 컨트롤 작성자가 전체 컨트롤을 단일 이벤트 소스로 보고하기 위해서 각 하위 구성 요소에서 발생할 수 있는 모든 가능한 입력 이벤트를 결합하려는 경우가 많습니다.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. 구성 요소 작성자에 게 즉시 표시 되는 정식 예제는이 WPF(Windows Presentation Foundation)Windows Presentation Foundation (WPF) Click 모든 단추가 포함 하는 직관적인 이벤트를 Button 처리 하는 모든 마우스 이벤트를 처리 하는 방법입니다. 이벤트입니다.The canonical example that is immediately visible to any component author is how a WPF(Windows Presentation Foundation)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. 마찬가지로는 ButtonBaseMouseLeftButtonUp클래스 처리기를 사용 합니다.Similarly, ButtonBase uses class handlers for MouseLeftButtonUp. 이벤트 데이터를 전달 하는 재정의에서 구현은를로 RoutedEventArgs true설정 Handled 하 여 해당 인스턴스를 처리 된 것으로 표시 하 고, 동일한 이벤트 데이터는 다른 클래스 처리기에 대 한 경로의 나머지 부분에 따라 계속 됩니다. 인스턴스 처리기 또는 이벤트 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 있는 처리기가 있는 경우 어떤 이유로 든 단추의 마우스 클릭은 루트 수준에서 또는 MouseLeftButtonUp 처리기를 호출 MouseLeftButtonDown 하지 않는다는 것을 알 수 있습니다.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 에 도달 하면 이벤트를 Click 더 의미 있는 것으로 MouseLeftButtonDown 대체 하기 때문에 클래스 처리에서를 처리 된 것으로 표시 했습니다.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. 이런 경우 두 가지 기술을 사용하여 처리기가 호출되게 할 수 있습니다.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. XAML(Extensible Application Markup Language)Extensible Application Markup Language (XAML)을 통해 이벤트 처리기 이름을 이벤트 특성 값으로 지정하는 단순한 구문으로는 이 동작을 활성화할 수 없습니다.The simple syntax of specifying the event handler name as an event attribute value via XAML(Extensible Application Markup Language)Extensible Application Markup Language (XAML) does not enable that behavior.

두 번째 방법은 라우트된 이벤트의 터널링 버전과 버블링 버전의 쌍을 만드는 것으로, 입력 이벤트에 대해서만 사용할 수 있습니다.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. Root 요소에서 처리 되 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