연결된 이벤트 개요

XAML(Extensible Application Markup Language)은 연결된 이벤트라는 언어 구성 요소 및 이벤트 유형을 정의합니다. 연결된 이벤트의 개념을 사용하면 실제로 정의하거나 이벤트를 상속하는 요소가 아닌 임의의 요소에 특정 이벤트의 핸들러를 추가할 수 있습니다. 이 경우 이벤트를 잠재적으로 발생시키는 개체나 인스턴스를 처리하는 대상이 정의하지 않으며 또는 그렇지 않으면 이벤트를 "소유"합니다.

필수 구성 요소

이 항목에서는 라우트된 이벤트 개요WPF의 XAML을 읽었다고 가정합니다.

연결된 이벤트 구문

연결된 이벤트에는 연결된 이벤트 사용량을 지원하기 위해 백업 코드에서 사용해야 하는 XAML 구문 및 코딩 패턴이 있습니다.

XAML 구문에서, 연결된 이벤트를 이벤트 이름뿐만 아니라 소유 형식과 이벤트 이름을 점(.)으로 구분하여 지정합니다. 이벤트 이름이 소유 형식의 이름으로 정규화되기 때문에, 연결된 이벤트 구문을 모든 연결된 이벤트를 인스턴스화할 수 있는 모든 요소에 연결할 수 있습니다.

예를 들어, 다음은 사용자 지정 NeedsCleaning 연결된 이벤트에 대해 핸들러를 연결하기 위한 XAML 구문입니다.

<aqua:Aquarium Name="theAquarium" Height="600" Width="800" aqua:AquariumFilter.NeedsCleaning="WashMe"/>

aqua: 접두사. 연결된 이벤트가 사용자 지정 맵핑된 xmlns에서 오는 사용자 지정 이벤트이기 때문에 이 경우에 접두사가 필요합니다.

WPF가 연결된 이벤트를 구현하는 방법

WPF에서 연결된 이벤트는 RoutedEvent 필드에 의해 지원되며 발생한 후 트리를 통해 라우팅됩니다. 일반적으로 연결된 이벤트(이벤트를 발생하는 개체)의 소스는 시스템이나 서비스 소스이며, 이벤트를 발생하는 코드를 실행하는 개체는 직접적인 요소 트리 파트가 아닙니다.

연결된 이벤트에 대한 시나리오

WPF에서 연결된 이벤트는 정적 Mouse 클래스 또는 Validation 클래스에 의해 활성화된 이벤트와 같은 서비스 수준 추상화가 있는 특정 기능 영역에 존재합니다. 서비스와 상호 작용하거나 사용하는 클래스는 연결된 이벤트 구문에서 이벤트를 사용하거나, 클래스가 서비스의 기능을 통합하는 방법의 일부인 라우트된 이벤트로 연결된 이벤트를 나타내도록 선택할 수 있습니다.

WPF는 연결된 이벤트 수를 정의하지만, 연결된 이벤트를 사용하거나 직접 처리하는 시나리오는 매우 제한됩니다. 일반적으로 연결된 이벤트는 아키텍처 용도로 사용되지만 연결되지 않은(CLR 이벤트 "래퍼"로 지원된) 라우트된 이벤트로 전달됩니다.

예를 들어 기본 연결된 이벤트 Mouse.MouseDown은 XAML이나 코드에서 연결된 이벤트 구문을 처리하는 대신 해당 UIElement에서 MouseDown을 사용하여 지정된 UIElement에서 더 쉽게 처리할 수 있습니다. 입력 디바이스의 향후 확장을 허용하므로 연결된 이벤트는 아키텍처의 용도로 사용됩니다. 가상의 디바이스는 마우스 입력을 시뮬레이션하기 위해 Mouse.MouseDown만 발생시키면 되며 그렇게 하기 위해 Mouse에서 파생될 필요는 없습니다. 그러나 이 시나리오는 이벤트를 처리하는 코드를 포함하며 연결된 이벤트의 XAML 처리는 이 시나리오와 관련이 없습니다.

WPF에서 연결된 이벤트 처리

연결된 이벤트를 처리하기 위한 프로세스 및 작성할 처리기 코드는 기본적으로 라우트된 이벤트의 경우와 동일합니다.

일반적으로 WPF 연결된 이벤트는 WPF 라우트된 이벤트와 크게 다르지 않습니다. 이벤트가 발생하는 방법 및 클래스에 의해 구성원으로 노출되는 방법에서 다릅니다(XAML 처리기 구문에도 영향을 미침).

그러나 앞서 설명한 것처럼, 기존 WPF 연결된 이벤트는 특별히 WPF 처리에 사용되지 않습니다. 이벤트의 목적은 합성 이벤트가 작성 시 부모 요소에 상태를 보고할 수 있게 하는 것으로, 이 경우 이벤트는 일반적으로 코드에서 발생하며 관련 부모 클래스에서 처리하는 클래스에도 사용됩니다. 예를 들어, Selector 내의 항목은 연결된 Selected 이벤트를 발생시킬 것으로 예상되며, 이 이벤트는 Selector 클래스에서 처리된 다음, Selector 클래스에서 잠재적으로 다른 라우트된 이벤트인 SelectionChanged로 변환됩니다. 라우트된 이벤트 및 클래스 처리에 대한 자세한 내용은 라우트된 이벤트를 처리된 것으로 표시 및 클래스 처리를 참조하십시오.

연결된 이벤트를 라우트된 이벤트로 정의

공통 WPF 기본 클래스에서 파생되는 경우, 클래스에 특정 패턴 메서드를 포함하고 기본 클래스에 이미 있는 유틸리티 메서드를 사용하여 자신의 연결된 이벤트를 구현할 수 있습니다.

패턴은 다음과 같습니다.

  • 두 개의 매개 변수가 있는 AddEventNameHandler 메서드. 첫 번째 매개 변수는 이벤트 처리기가 추가되는 인스턴스입니다. 두 번째 매개 변수는 추가할 이벤트 처리기입니다. 메서드는 반환 값이 없는 publicstatic이어야 합니다.

  • 두 개의 매개 변수가 있는 RemoveEventNameHandler 메서드. 첫 번째 매개 변수는 이벤트 처리기가 제거되는 인스턴스입니다. 두 번째 매개 변수는 제거할 이벤트 처리기입니다. 메서드는 반환 값이 없는 publicstatic이어야 합니다.

연결된 이벤트 처리기 특성이 요소에 선언될 때 AddEventNameHandler 접근자 메서드는 XAML 처리를 용이하게 합니다. AddEventNameHandlerRemoveEventNameHandler 메서드도 연결된 이벤트의 이벤트 처리기 저장소에 대한 코드 액세스를 사용하도록 설정합니다.

지정된 모든 XAML 판독기 구현에 지원하는 언어 및 아키텍처의 기본 이벤트를 식별하기 위한 다른 스키마가 있을 수 있기 때문에 이 일반 패턴은 프레임워크에 실질적으로 구현할 수 있을 만큼 정확하지 않습니다. WPF가 연결된 이벤트를 라우트된 이벤트로 구현하는 이유 중 하나입니다. 이벤트에 사용할 식별자(RoutedEvent)는 WPF 이벤트 시스템에서 이미 정의되어 있습니다. 또한 이벤트 라우팅은 연결된 이벤트의 XAML 언어 수준 개념에 대한 자연스러운 구현 확장입니다.

WPF 연결 이벤트의 AddEventNameHandler 구현은 라우트된 이벤트와 처리기를 인수로 사용하여 AddHandler 호출로 구성됩니다.

이 구현 전략 및 라우트된 이벤트 시스템은 일반적으로 연결된 이벤트에 대한 처리를 UIElement 파생 클래스 또는 ContentElement 파생 클래스로 제한합니다. 이러한 클래스에만 AddHandler 구현이 있기 때문입니다.

예를 들어, 다음 코드는 연결된 이벤트를 라우트된 이벤트로 선언하는 WPF 연결된 이벤트 전략을 사용하여, 소유자 클래스 Aquarium에서 NeedsCleaning 연결된 이벤트를 정의합니다.

public static readonly RoutedEvent NeedsCleaningEvent = EventManager.RegisterRoutedEvent("NeedsCleaning", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AquariumFilter));
public static void AddNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
{
    UIElement uie = d as UIElement;
    if (uie != null)
    {
        uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler);
    }
}
public static void RemoveNeedsCleaningHandler(DependencyObject d, RoutedEventHandler handler)
{
    UIElement uie = d as UIElement;
    if (uie != null)
    {
        uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler);
    }
}
Public Shared ReadOnly NeedsCleaningEvent As RoutedEvent = EventManager.RegisterRoutedEvent("NeedsCleaning", RoutingStrategy.Bubble, GetType(RoutedEventHandler), GetType(AquariumFilter))
Public Shared Sub AddNeedsCleaningHandler(ByVal d As DependencyObject, ByVal handler As RoutedEventHandler)
    Dim uie As UIElement = TryCast(d, UIElement)
    If uie IsNot Nothing Then
        uie.AddHandler(AquariumFilter.NeedsCleaningEvent, handler)
    End If
End Sub
Public Shared Sub RemoveNeedsCleaningHandler(ByVal d As DependencyObject, ByVal handler As RoutedEventHandler)
    Dim uie As UIElement = TryCast(d, UIElement)
    If uie IsNot Nothing Then
        uie.RemoveHandler(AquariumFilter.NeedsCleaningEvent, handler)
    End If
End Sub

연결된 이벤트 식별자 필드, RegisterRoutedEvent를 설정하는 데 사용된 메서드는 실제로 연결되지 않은 라우트된 이벤트를 등록하는 데 사용되는 메서드와 동일합니다. 연결된 이벤트 및 라우트된 이벤트 모두 중앙 집중화된 내부 저장소에 등록됩니다. 이 이벤트 저장소 구현은 라우트된 이벤트 개요에서 설명하는 “인터페이스로서의 이벤트” 개념 고려 사항을 사용합니다.

WPF 연결된 이벤트 발생

일반적으로 기존 WPF 정의 연결된 이벤트를 코드에서 발생시킬 필요가 없습니다. 이러한 이벤트는 일반 "서비스" 개념적 모델을 따르며, InputManager와 같은 서비스 클래스는 이벤트를 발생시키는 작업을 담당합니다.

그러나 RoutedEvent를 기반으로 연결된 이벤트의 WPF 모델을 기반으로 사용자 지정 연결된 이벤트를 정의하는 경우 RaiseEvent를 사용하여 UIElement 또는 ContentElement에서 연결된 이벤트를 발생시킬 수 있습니다. 라우트된 이벤트(연결된 또는 연결되지 않은)를 발생시키려면 요소 트리의 특정 요소를 이벤트 소스로 선언해야 하며, 이 소스는 RaiseEvent 호출자로 보고됩니다. 트리에서 소스로 보고되는 요소 판별은 서비스에 따라 다릅니다.

참고 항목