다음을 통해 공유


이벤트 및 라우트된 이벤트 개요

중요 API

프로그래밍 언어로 C#, Visual Basic 또는 Visual C++ 구성요소 확장(C++/CX)을 사용하고 UI 정의에 XAML을 사용할 때 Windows 런타임 앱의 이벤트 프로그래밍 개념에 대해 설명합니다. XAML에서 UI 요소에 대한 선언의 일부로 이벤트에 대한 처리기를 할당하거나 코드에 처리기를 추가할 수 있습니다. Windows 런타임은 라우트된 이벤트를 지원합니다. 특정 입력 이벤트 및 데이터 이벤트는 이벤트를 발생시킨 개체 이외의 개체에서 처리할 수 있습니다. 라우트 된 이벤트는 컨트롤 템플릿을 정의하거나 페이지 또는 레이아웃 컨테이너를 사용할 때 유용합니다.

프로그래밍 개념으로서의 이벤트

일반적으로 Windows 런타임 앱을 프로그래밍할 때의 이벤트 개념은 가장 인기 있는 프로그래밍 언어의 이벤트 모델과 유사합니다. Microsoft .NET 또는 C++ 이벤트를 이미 사용하는 방법을 알고 있는 경우 시작이 시작됩니다. 그러나 처리기 연결과 같은 몇 가지 기본 작업을 수행하기 위해 이벤트 모델 개념에 대해 잘 알 필요는 없습니다.

C#, Visual Basic 또는 C++/CX를 프로그래밍 언어로 사용하면 UI가 태그(XAML)로 정의됩니다. XAML 태그 구문에서 태그 요소와 런타임 코드 엔터티 간에 이벤트를 연결하는 몇 가지 원칙은 ASP.NET 또는 HTML5와 같은 다른 웹 기술과 유사합니다.

참고 XAML 정의 UI에 대한 런타임 논리를 제공하는 코드를 코드 숨김 또는 코드 숨김 파일이라고도 합니다. Microsoft Visual Studio 솔루션 보기에서 이 관계는 그래픽으로 표시되며 코드 숨김 파일은 참조하는 XAML 페이지와 비교해 종속적이고 중첩된 파일입니다.

Button.Click: 이벤트 및 XAML 소개

Windows 런타임 앱에 대한 가장 일반적인 프로그래밍 작업 중 하나는 UI에 대한 사용자 입력을 캡처하는 것입니다. 예를 들어 UI에 사용자가 정보를 제출하거나 상태를 변경하기 위해 클릭해야 하는 단추가 있을 수 있습니다.

XAML을 생성하여 Windows 런타임 앱에 대한 UI를 정의합니다. 이 XAML은 일반적으로 Visual Studio의 디자인 화면에서 출력됩니다. 일반 텍스트 편집기 또는 타사 XAML 편집기에서 XAML을 작성할 수도 있습니다. 해당 XAML을 생성하는 동안 개별 UI 요소에 대한 이벤트 처리기를 동시에 연결하여 해당 UI 요소의 속성 값을 설정하는 다른 모든 XAML 특성을 정의할 수 있습니다.

XAML에서 이벤트를 연결하려면 이미 정의했거나 코드 숨김의 뒷부분에서 정의할 처리기 메서드의 문자열 형식 이름을 지정합니다. 예를 들어 이 XAML은 다른 속성(x:Name 특성, Content)이 특성으로 할당된 Button 개체를 정의하고 다음 메서드를 참조하여 단추의 ClickShowUpdatesButton_Click 이벤트에 대한 처리기를 연결합니다.

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

이벤트 배선 은 프로그래밍 용어입니다. 이벤트 발생 시 명명된 처리기 메서드를 호출해야 함을 나타내는 프로세스 또는 코드를 참조합니다. 대부분의 절차 코드 모델에서 이벤트 배선은 이벤트와 메서드의 이름을 모두 지정하는 암시적 또는 명시적 "AddHandler" 코드이며 일반적으로 대상 개체 인스턴스를 포함합니다. XAML에서 "AddHandler"는 암시적이며 이벤트 배선은 전적으로 이벤트 이름을 개체 요소의 특성 이름으로 지정하고 처리기의 이름을 해당 특성 값으로 지정하는 것으로 구성됩니다.

모든 앱의 코드 및 코드 숨김에 사용하는 프로그래밍 언어로 실제 처리기를 작성합니다. 특성을 Click="ShowUpdatesButton_Click"사용하여 XAML이 태그 컴파일 및 구문 분석될 때 IDE의 빌드 작업에서 XAML 태그 컴파일 단계와 앱이 로드될 때 최종 XAML 구문 분석에서 앱 코드의 일부로 명명된 ShowUpdatesButton_Click 메서드를 찾을 수 있는 계약을 만들었습니다. ShowUpdatesButton_ClickClick 이벤트의 모든 처리기에 대해 대리자를 기반으로 호환되는 메서드 서명을 구현하는 메서드여야 합니다. 예를 들어 이 코드는 처리기를 ShowUpdatesButton_Click 정의합니다.

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 대리자를 기반으로 합니다. Click 메서드에 대한 구문에 이름이 지정된 대리자를 확인하게 되므로 이 대리자를 사용할 대리자로 알고 있는 것이 좋습니다.

Visual Studio는 XAML을 편집하는 동안 이벤트 처리기의 이름을 지정하고 처리기 메서드를 정의하는 편리한 방법을 제공합니다. XAML 텍스트 편집기에서 이벤트의 특성 이름을 제공하는 경우 Microsoft IntelliSense 목록이 표시될 때까지 잠시 기다립니다. 목록에서 새 이벤트 처리기를<> 클릭하면 Microsoft Visual Studio에서 요소의 x:Name(또는 형식 이름), 이벤트 이름 및 숫자 접미사를 기반으로 메서드 이름을 제안합니다. 그런 다음 선택한 이벤트 처리기 이름을 마우스 오른쪽 단추로 클릭하고 이벤트 처리기로 탐색을 클릭 할 수 있습니다. 그러면 XAML 페이지에 대한 코드 숨김 파일의 코드 편집기 보기에 표시된 것처럼 새로 삽입된 이벤트 처리기 정의로 직접 이동합니다. 이벤트 처리기에는 보낸 사람 매개 변수 및 이벤트가 사용하는 이벤트 데이터 클래스를 포함하여 올바른 서명이 이미 있습니다. 또한 올바른 서명이 있는 처리기 메서드가 코드 숨김에 이미 있는 경우 해당 메서드의 이름은 새 이벤트 처리기<> 옵션과 함께 자동 완성 드롭다운에 나타납니다. IntelliSense 목록 항목을 클릭하는 대신 Tab 키를 바로 가기로 누를 수도 있습니다.

이벤트 처리기 정의

UI 요소이고 XAML에 선언된 개체의 경우 이벤트 처리기 코드는 XAML 페이지의 코드 숨김 역할을 하는 부분 클래스에 정의됩니다. 이벤트 처리기는 XAML과 연결된 partial 클래스의 일부로 작성하는 메서드입니다. 이러한 이벤트 처리기는 특정 이벤트가 사용하는 대리자를 기반으로 합니다. 이벤트 처리기 메서드는 퍼블릭 또는 프라이빗일 수 있습니다. 프라이빗 액세스는 XAML에서 만든 처리기와 인스턴스가 궁극적으로 코드 생성에 의해 조인되기 때문에 작동합니다. 일반적으로 클래스에서 이벤트 처리기 메서드를 비공개로 만드는 것이 좋습니다.

참고 C++에 대한 이벤트 처리기는 부분 클래스에서 정의되지 않으며 헤더에서 프라이빗 클래스 멤버로 선언됩니다. C++ 프로젝트에 대한 빌드 작업은 C++용 XAML 형식 시스템 및 코드 숨김 모델을 지원하는 코드 생성을 처리합니다.

보낸 사람 매개 변수 및 이벤트 데이터

이벤트에 대해 작성하는 처리기는 처리기가 호출되는 각 사례에 대한 입력으로 사용할 수 있는 두 값에 액세스할 수 있습니다. 첫 번째는 값은로, 처리기가 결합된 객체에 대한 참조입니다. 보낸 사람 매개 변수는 기본 개체 형식으로 입력됩니다. 일반적인 방법은 발신자를 보다 정확한 형식으로 캐스팅하는 것입니다. 이 기술은 보낸 사람 개체 자체에서 상태를 검사 변경하려는 경우에 유용합니다. 사용자 고유의 앱 디자인에 따라 일반적으로 처리기가 연결된 위치 또는 다른 디자인 세부 사항에 따라 발신자를 캐스팅하기에 안전한 형식을 알고 있습니다.

두 번째 값은 이벤트 데이터로, 주로 syntax 정의에서 또는 매개 변수로 나타납니다. 처리 중인 특정 이벤트에 대해 할당된 대리자의 e 매개 변수를 확인하고 Visual Studio에서 IntelliSense 또는 개체 브라우저를 사용하여 사용할 수 있는 이벤트 데이터의 속성을 검색할 수 있습니다. 또는 Windows 런타임 참조 설명서를 사용할 수 있습니다.

일부 이벤트의 경우 이벤트 데이터의 특정 속성 값은 이벤트가 발생했음을 아는 것만큼이나 중요합니다. 이는 특히 입력 이벤트의 경우입니다. 포인터 이벤트의 경우 이벤트가 발생했을 때 포인터의 위치가 중요할 수 있습니다. 키보드 이벤트의 경우 가능한 모든 키를 누르면 KeyDown KeyUp 이벤트가 발생합니다. 사용자가 누른 키를 확인하려면 이벤트 처리기에서 사용할 수 있는 KeyRoutedEventArgs 에 액세스해야 합니다. 입력 이벤트 처리에 대한 자세한 내용은 키보드 조작포인터 입력 처리를 참조하세요. 입력 이벤트 및 입력 시나리오에는 포인터 이벤트에 대한 포인터 캡처, 키보드 이벤트에 대한 한정자 키 및 플랫폼 키 코드와 같이 이 항목에서 다루지 않는 추가 고려 사항이 있는 경우가 많습니다.

비동기 패턴을 사용하는 이벤트 처리기

경우에 따라 이벤트 처리기 내에서 비동기 패턴을 사용하는 API를 사용하려고 합니다. 예를 들어 AppBar 단추를 사용하여 파일 선택기를 표시하고 상호 작용할 수 있습니다. 그러나 대부분의 파일 선택 API는 비동기적입니다. 비동기/대기 가능한 범위 내에서 호출해야 하며 컴파일러가 이를 적용합니다. 따라서 처리기가 비동기 void가 되도록 이벤트 처리기에 비동 기 키워드를 추가할 수 있습니다. 이제 이벤트 처리기가 비동기/대기 가능 호출을 할 수 있습니다.

비동기 패턴을 사용하는 사용자 상호 작용 이벤트 처리의 예는 파일 액세스 및 선택기(C# 또는 Visual Basic 시리즈를 사용하여 첫 번째 Windows 런타임 앱 만들기의 일부)를 참조하세요. [C에서 비동기 API 호출)도 참조하세요.

코드에 이벤트 처리기 추가

XAML은 개체에 이벤트 처리기를 할당하는 유일한 방법은 아닙니다. XAML에서 사용할 수 없는 개체를 포함하여 코드의 지정된 개체에 이벤트 처리기를 추가하려면 이벤트 처리기를 추가하는 데 언어별 구문을 사용할 수 있습니다.

C#에서 구문은 연산자를 += 사용하는 것입니다. 연산자의 오른쪽에 있는 이벤트 처리기 메서드 이름을 참조하여 처리기를 등록합니다.

런타임 UI에 표시되는 개체에 이벤트 처리기를 추가하는 코드를 사용하는 경우 일반적으로 로드 또는 OnApplyTemplate과 같은 개체 수명 이벤트 또는 콜백에 대한 응답으로 이러한 처리기를 추가하여 관련 개체의 이벤트 처리기가 런타임에 사용자가 시작한 이벤트에 대해 준비되도록 하는 것입니다. 이 예제에서는 페이지 구조의 XAML 개요를 보여 준 다음 개체에 이벤트 처리기를 추가 하기 위한 C# 언어 구문을 제공 합니다.

<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;
}

더 자세한 구문이 있는 점 참고하십시오. 2005년 C#에서는 컴파일러가 새 대리자 인스턴스를 유추하고 이전의 간단한 구문을 사용하도록 설정하는 대리자 유추라는 기능을 추가했습니다. 자세한 구문은 이전 예제와 기능적으로 동일하지만 등록하기 전에 새 대리자 인스턴스를 명시적으로 만들므로 대리자 유추를 활용하지 않습니다. 이 명시적 구문은 덜 일반적이지만 일부 코드 예제에서는 여전히 볼 수 있습니다.

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

Visual Basic 구문에는 두 가지 가능성이 있습니다. 하나는 C# 구문을 병렬로 처리하고 처리기를 인스턴스에 직접 연결하는 것입니다. 이렇게 하려면 AddHandler 키워드(keyword) 처리기 메서드 이름을 역참조하는 AddressOf 연산자도 필요합니다.

Visual Basic 구문의 다른 옵션은 이벤트 처리기에서 Handles 키워드(keyword) 사용하는 것입니다. 이 기술은 처리기가 로드 시 개체에 존재하고 개체 수명 동안 유지되어야 하는 경우에 적합합니다. XAML에 정의된 개체에 핸들을 사용하려면 이름 x:Name / 을 제공해야 합니다. 이 이름은 Handles 구문의 Instance.Event 부분에 필요한 인스턴스 한정자가 됩니다. 이 경우 다른 이벤트 처리기 연결을 시작하기 위해 개체 수명 기반 이벤트 처리기가 필요하지 않습니다. 핸들 연결은 XAML 페이지를 컴파일할 때 만들어집니다.

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

Visual Studio 및 해당 XAML 디자인 화면은 일반적으로 Handles 키워드(keyword) 대신 인스턴스 처리 기술을 승격합니다. XAML에서 이벤트 처리기 배선을 설정하는 것은 일반적인 디자이너-개발자 워크플로의 일부이며 Handles 키워드(keyword) 기술은 XAML의 이벤트 처리기 배선과 호환되지 않습니다.

C++/CX에서는 += 구문도 사용하지만 기본적인 C# 형태와 다음과 같은 차이점이 있습니다.

  • 대리자 유추가 없으므로 대리자 인스턴스에 ref new를 사용해야 합니다.
  • 대리자 생성자에는 두 개의 매개 변수가 있으며 첫 번째 매개 변수로 대상 개체가 필요합니다. 일반적으로 이를 지정합니다.
  • 대리자 생성자에는 메서드 주소가 두 번째 매개 변수로 필요하므로 &참조 연산자가 메서드 이름 앞에 섰습니다.
textBlock1().PointerEntered({this, &MainPage::TextBlock1_PointerEntered });
textBlock1->PointerEntered += 
ref new PointerEventHandler(this, &BlankPage::textBlock1_PointerEntered);

코드에서 이벤트 처리기 제거

코드에서 이벤트 처리기를 추가한 경우에도 일반적으로 코드에서 이벤트 처리기를 제거할 필요는 없습니다. 페이지 및 컨트롤과 같은 대부분의 Windows 런타임 개체에 대한 개체 수명 동작은 기본 Window 및 해당 시각적 트리에서 연결이 끊어지면 개체가 삭제되고 대리자 참조도 제거됩니다. .NET은 가비지 수집을 통해 이 작업을 수행하고 C++/CX를 사용하는 Windows 런타임 기본적으로 약한 참조를 사용합니다.

이벤트 처리기를 명시적으로 제거하려는 드문 경우가 있습니다. 여기에는 다음이 포함됩니다.

  • 기존 방식으로 가비지 수집을 가져올 수 없는 정적 이벤트에 대해 추가한 처리기입니다. Windows 런타임 API의 정적 이벤트의 예는 CompositionTarget클립보드 클래스의 이벤트입니다.
  • 처리기 제거 타이밍을 즉시 수행하려는 코드 또는 런타임에 이벤트에 대한 이전/새 이벤트 처리기를 교환할 코드를 테스트합니다.
  • 사용자 지정 제거 접근자의 구현입니다.
  • 사용자 지정 정적 이벤트입니다.
  • 페이지 탐색에 대한 처리기입니다.

FrameworkElement.Unloaded 또는 Page.NavigatedFrom은 다른 이벤트 처리기를 제거하는 데 사용할 수 있도록 상태 관리 및 개체 수명에서 적절한 위치에 있는 가능한 이벤트 트리거입니다.

예를 들어 다음 코드를 사용하여 대상 개체 textBlock1에서 textBlock1_PointerEntered라는 이벤트 처리기를 제거할 수 있습니다.

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

XAML 특성을 통해 이벤트가 추가된 경우 처리기를 제거할 수도 있습니다. 즉, 처리기가 생성된 코드에 추가되었습니다. 처리기가 연결된 요소에 대해 Name 값을 제공한 경우 나중에 코드에 대한 개체 참조를 제공하기 때문에 이 작업을 더 쉽게 수행할 수 있습니다. 그러나 개체에 Name이 없는 경우 필요한 개체 참조를 찾기 위해 개체 트리를 탐색할 수도 있습니다.

C++/CX에서 이벤트 처리기를 제거해야 하는 경우 이벤트 처리기 등록의 반환 값에서 받은 등록 토큰이 += 필요합니다. C++/CX 구문에서 등록 취소의 -= 오른쪽에 사용하는 값이 메서드 이름이 아닌 토큰이기 때문입니다. C++/CX의 경우 C++/CX 생성 코드가 토큰을 저장하지 않으므로 XAML 특성으로 추가된 처리기를 제거할 수 없습니다.

라우트된 이벤트

C#, Microsoft Visual Basic 또는 C++/CX를 사용하는 Windows 런타임 대부분의 UI 요소에 있는 이벤트 집합에 대해 라우트 된 이벤트의 개념을 지원합니다. 이러한 이벤트는 입력 및 사용자 상호 작용 시나리오를 위한 것이며 UIElement 기본 클래스에서 구현됩니다. 다음은 라우트 된 이벤트인 입력 이벤트 목록입니다.

라우트 된 이벤트는 자식 개체에서 개체 트리의 각 연속 부모 개체로 전달(라우트)되는 이벤트입니다. UI의 XAML 구조는 이 트리와 근사치를 하며, 해당 트리의 루트는 XAML의 루트 요소입니다. 개체 트리에는 속성 요소 태그와 같은 XAML 언어 기능이 포함되지 않으므로 실제 개체 트리는 XAML 요소 중첩과 다소 다를 수 있습니다. 라우트 된 이벤트를 이벤트를 발생시키는 XAML 개체 요소 자식 요소에서 이벤트를 포함하는 부모 개체 요소로 버블링 하는 것으로 생각할 수 있습니다. 이벤트 및 이벤트 데이터는 이벤트 경로를 따라 여러 개체에서 처리할 수 있습니다. 처리기가 있는 요소가 없으면 루트 요소에 도달할 때까지 경로가 계속 진행됩니다.

DHTML(동적 HTML) 또는 HTML5와 같은 웹 기술을 알고 있는 경우 버블링 이벤트 개념에 이미 익숙할 수 있습니다.

라우트 된 이벤트가 이벤트 경로를 통해 버블되면 연결된 이벤트 처리기는 모두 이벤트 데이터의 공유 인스턴스에 액세스합니다. 따라서 처리기에서 이벤트 데이터를 쓸 수 있는 경우 이벤트 데이터에 대한 변경 내용이 다음 처리기에 전달되고 더 이상 이벤트의 원래 이벤트 데이터를 나타내지 않을 수 있습니다. 이벤트에 라우트 된 이벤트 동작이 있는 경우 참조 설명서에는 라우트 된 동작에 대한 설명 또는 기타 표기법이 포함됩니다.

RoutedEventArgs의 OriginalSource 속성

이벤트가 이벤트 경로를 버블업하는 경우 발신자 는 더 이상 이벤트 발생 개체와 동일한 개체가 아닙니다. 대신 발신자 는 호출되는 처리기가 연결된 개체입니다.

경우에 따라 발신자 는 흥미롭지 않으며 포인터 이벤트가 발생할 때 포인터가 끝난 가능한 자식 개체 또는 사용자가 키보드 키를 누를 때 포커스가 있는 더 큰 UI의 개체와 같은 정보에 관심이 있습니다. 이러한 경우 OriginalSource 속성의 값을 사용할 수 있습니다. 경로 의 모든 지점에서 OriginalSource 는 처리기가 연결된 개체 대신 이벤트를 발생시킨 원래 개체를 보고합니다. 그러나 UIElement 입력 이벤트의 경우 원래 개체는 종종 페이지 수준 UI 정의 XAML에 즉시 표시되지 않는 개체입니다. 대신 원래 원본 개체는 컨트롤의 템플릿이 있는 부분일 수 있습니다. 예를 들어 사용자가 단추가장자리 위에 포인터를 가져가면 대부분의 포인터 이벤트에 대해 OriginalSource단추 자체가 아니라 템플릿테두리 템플릿 부분입니다.

입력 이벤트 버블링 템플릿 컨트롤을 만드는 경우에 특히 유용 합니다. 템플릿이 있는 모든 컨트롤에는 소비자가 새 템플릿을 적용할 수 있습니다. 작업 템플릿을 다시 만들려고 하는 소비자는 기본 템플릿에 선언된 일부 이벤트 처리를 의도치 않게 제거할 수 있습니다. 클래스 정의에서 OnApplyTemplate 재정의의 일부로 처리기를 연결하여 제어 수준 이벤트 처리를 제공할 수 있습니다. 그런 다음 인스턴스화 시 컨트롤의 루트까지 버블업되는 입력 이벤트를 catch할 수 있습니다.

Handled 속성

특정 라우트 된 이벤트에 대한 여러 이벤트 데이터 클래스에는 Handled라는 속성이 포함되어 있습니다. 예제는 PointerRoutedEventArgs.Handled, KeyRoutedEventArgs.Handled, DragEventArgs.Handled를 참조하세요. 모든 경우에 Handled 는 설정 가능한 부울 속성입니다.

Handled 속성을 true로 설정하면 이벤트 시스템 동작에 영향을 줍니다. Handled가 true대부분의 이벤트 처리기에 대한 라우팅이 중지됩니다. 이벤트는 경로를 따라 계속 진행되어 해당 특정 이벤트 사례의 다른 연결된 처리기에 알리지 않습니다. 이벤트의 컨텍스트에서 "처리됨"의 의미와 앱이 이벤트에 응답하는 방식은 사용자에게 달려 있습니다. 기본적으로 Handled 는 이벤트 발생이 컨테이너에 버블링할 필요가 없다는 것을 앱 코드가 명시할 수 있도록 하는 간단한 프로토콜이며, 앱 논리는 필요한 작업을 처리했습니다. 그러나 반대로 기본 제공 시스템이나 제어 동작이 작동할 수 있도록 버블링해야 할 수도 있는 이벤트를 처리하지 않도록 주의해야 합니다. 예를 들어 선택 컨트롤의 일부 또는 항목 내에 있는 하위 수준 이벤트 처리가 저하될 수 있습니다. 선택 컨트롤은 선택 영역이 변경되어야 한다는 것을 알 수 있는 입력 이벤트를 찾고 있을 수 있습니다.

모든 라우트 된 이벤트가 이러한 방식으로 경로를 취소할 수 있는 것은 아니며 Handled 속성이 없으므로 이를 알 수 있습니다. 예를 들어 GotFocusLostFocus는 거품을 발생하지만 항상 루트에 버블링되며 이벤트 데이터 클래스에는 해당 동작에 영향을 줄 수 있는 Handled 속성이 없습니다.

컨트롤의 입력 이벤트 처리기

특정 Windows 런타임 컨트롤은 때때로 내부적으로 입력 이벤트에 대해 Handled 개념을 사용합니다. 사용자 코드에서 처리할 수 없으므로 입력 이벤트가 발생하지 않는 것처럼 보일 수 있습니다. 예를 들어 Button 클래스에는 PointerPressed 일반 입력 이벤트를 의도적으로 처리하는 논리가 포함됩니다. 단추가 포인터 눌림 입력에 의해 시작되는 Click 이벤트뿐만 아니라 포커스가 있을 때 단추를 호출할 수 있는 Enter 키와 같은 키 처리와 같은 다른 입력 모드에서 실행되기 때문입니다. Button 클래스 디자인을 위해 원시 입력 이벤트는 개념적으로 처리되고 사용자 코드와 같은 클래스 소비자는 컨트롤 관련 Click 이벤트와 상호 작용할 수 있습니다. Windows 런타임 API 참조의 특정 컨트롤 클래스에 대한 항목에서는 종종 클래스가 구현하는 이벤트 처리 동작을 기록해 둡니다. 경우에 따라 On 이벤트 메서드를 재정의하여 동작을 변경할 수 있습니다. 예를 들어 Control.OnKeyDown을 재정의하여 TextBox 파생 클래스가 키 입력에 반응하는 방식을 변경할 수 있습니다.

이미 처리 된 라우트 된 이벤트에 대한 처리기 등록

앞서, Handled를 true로 설정하면 대부분의 처리기가 호출되지 않도록 방지한다고 말씀드렸습니다. 그러나 AddHandler 메서드는 경로의 앞부분에 있는 다른 처리기가 공유 이벤트 데이터에서 Handled를 true설정한 경우에도 항상 경로에 대해 호출되는 처리기를 연결할 수 있는 기술을 제공합니다. 이 기술은 사용 중인 컨트롤이 내부 작성 또는 컨트롤별 논리에서 이벤트를 처리한 경우에 유용합니다. 하지만 여전히 컨트롤 인스턴스 또는 앱 UI에서 응답하려고 합니다. 그러나 이 기술은 Handled의 목적과 모순되고 컨트롤의 의도된 상호 작용을 깨뜨릴 수 있으므로 주의해서 사용합니다.

식별자는 AddHandler 메서드의 필수 입력이므로 해당 라우트 된 이벤트 식별자가 있는 라우트 된 이벤트만 AddHandler 이벤트 처리 기술을 사용할 수 있습니다. 사용 가능한 라우트 된 이벤트 식별자가 있는 이벤트 목록은 AddHandler에 대한 참조 설명서를 참조하세요. 대부분의 경우 앞에서 보여 준 라우트 된 이벤트 목록과 동일합니다. 예외는 목록의 마지막 두 항목인 GotFocusLostFocus에 라우트 된 이벤트 식별자가 없으므로 해당 항목에 대해 AddHandler를 사용할 수 없다는 것입니다.

시각적 트리 외부의 라우트 된 이벤트

특정 개체는 개념적으로 기본 시각적 개체에 오버레이가 있는 것과 같은 기본 시각적 트리와의 관계에 참여합니다. 이러한 개체는 모든 트리 요소를 시각적 루트에 연결하는 일반적인 부모-자식 관계의 일부가 아닙니다. 표시된 팝업 또는 도구 설명의 경우입니다. Popup 또는 ToolTip에서 라우트 된 이벤트를 처리하려면 Popup 또는 ToolTip 요소 자체가 아닌 Popup 또는 ToolTip 내에 있는 특정 UI 요소에 처리기를 배치합니다. 팝업 또는 도구 설명 콘텐츠에 대해 수행되는 모든 작성 내에서 라우팅에 의존하지 마세요. 라우트 된 이벤트에 대한 이벤트 라우팅은 기본 시각적 트리에서만 작동하기 때문입니다. Popup 또는 ToolTip은 자회사 UI 요소의 부모로 간주되지 않으며 팝업 기본 배경과 같은 항목을 입력 이벤트의 캡처 영역으로 사용하려고 하더라도 라우트된 이벤트를 수신하지 않습니다.

적중 횟수 테스트 및 이벤트

UI에서 요소가 마우스, 터치 및 스타일러스 입력에 표시되는지 여부와 위치를 적중 테스트라고 합니다. 터치 동작과 터치 동작의 결과로써 발생한 상호작용별/조작 이벤트의 경우, 이벤트 소스가 되고 동작과 연결된 이벤트를 실행하려면 요소가 적중 테스트에 표시되어야 합니다. 그렇지 않으면 동작은 해당 입력과 상호 작용할 수 있는 시각적 트리의 모든 기본 요소 또는 부모 요소에 요소를 전달합니다. 적중 테스트에 영향을 주는 몇 가지 요인이 있지만 지정된 요소가 IsHitTestVisible 속성을 검사 입력 이벤트를 실행할 수 있는지 여부를 확인할 수 있습니다. 이 속성은 요소가 다음 조건을 충족하는 경우에만 true를 반환합니다.

  • 요소의 Visibility 속성 값이 Visible입니다.
  • 요소의 Background 또는 Fill 속성 값이 null이 아닙니다. null 브러시 값을 사용하면 투명도가 생성되고 적중 테스트가 보이지 않습니다. (요소를 투명하게 만들지만 적중 횟수 테스트가 가능하도록 하려면 null 대신 투명 브러시를 사용하십시오.)

참고 배경 및 채우기는 UIElement에서 정의되지 않으며 대신 Control 및 Shape같은 다른 파생 클래스에 의해 정의됩니다. 그러나 포그라운드 및 배경 속성에 사용하는 브러시의 의미는 속성을 구현하는 하위 클래스에 관계없이 적중 횟수 테스트 및 입력 이벤트에 대해 동일합니다.

일부 컨트롤에는 적중 테스트에 대한 특별한 규칙이 있습니다. 예를 들어 TextBlock 에는 Background 속성이 없지만 차원의 전체 영역 내에서 테스트할 수 있습니다. ImageMediaElement 컨트롤은 표시될 미디어 원본 파일의 알파 채널 같은 투명 콘텐츠와 관계없이 정의된 사각형 차원에 대해 적중 횟수 테스트가 가능합니다. WebView 컨트롤에는 입력이 호스트된 HTML에 의해 처리될 수 있고 스크립트 이벤트를 발생시킬 수 있기 때문에 특수 적중 횟수 테스트 동작이 있습니다.

대부분의 패널 클래스와 테두리 는 자체 백그라운드에서 적중 테스트할 수 없지만 포함된 요소에서 라우팅 되는 사용자 입력 이벤트를 여전히 처리할 수 있습니다.

요소의 적중 테스트 가능 여부에 관계없이 사용자 입력 이벤트와 동일한 위치에 있는 요소를 확인할 수 있습니다. 이렇게 하려면 FindElementsInHostCoordinates 메서드를 호출 합니다 . 이름에서 알 수 있듯이 이 메서드는 지정된 호스트 요소를 기준으로 한 위치에서 요소를 찾습니다. 그러나 적용된 변환 및 레이아웃 변경은 요소의 상대 좌표계를 조정할 수 있으므로 지정된 위치에 있는 요소에 영향을 줄 수 있습니다.

명령

소수의 UI 요소는 명령을 지원 합니다. 명령에서는 기본 구현에서 입력 관련 라우트 된 이벤트를 사용하고 단일 명령 처리기를 호출하여 관련 UI 입력(특정 포인터 작업, 특정 가속기 키)을 처리할 수 있습니다. UI 요소에 명령을 사용할 수 있는 경우에는 개별 입력 이벤트 대신 명령 API를 사용하는 것이 좋습니다. 일반적으로 데이터에 대한 뷰 모델을 정의하는 클래스의 속성에 바인딩 참조를 사용합니다. 속성에는 언어별 ICommand 명령 패턴을 구현하는 명명된 명령이 있습니다. 자세한 내용은 ButtonBase.Command을 참조하세요.

Windows 런타임 사용자 지정 이벤트

사용자 지정 이벤트를 정의하기 위해 이벤트를 추가하는 방법 및 클래스 디자인의 의미는 사용 중인 프로그래밍 언어에 따라 크게 달라집니다.

  • C# 및 Visual Basic의 경우 CLR 이벤트를 정의합니다. 사용자 지정 접근자를 사용하지 않는 한 표준 .NET 이벤트 패턴을 사용할 수 있습니다(제거/ 추가). 추가적인 팁:
  • C++/CX의 경우 이벤트(C++/CX)를 참조하세요.
    • 사용자 지정 이벤트를 직접 사용하는 경우에도 명명된 참조를 사용합니다. 사용자 지정 이벤트에 람다를 사용하지 말고 순환 참조를 만들 수 있습니다.

Windows 런타임 대한 사용자 지정 라우트 된 이벤트를 선언할 수 없습니다. 라우트 된 이벤트는 Windows 런타임 제공되는 집합으로 제한됩니다.

사용자 지정 이벤트 정의는 일반적으로 사용자 지정 컨트롤을 정의하는 연습의 일부로 수행됩니다. 속성 변경 콜백이 있는 종속성 속성을 사용하고 일부 또는 모든 경우에 종속성 속성 콜백에 의해 발생하는 사용자 지정 이벤트를 정의하는 것이 일반적인 패턴입니다. 컨트롤의 소비자는 정의한 속성 변경 콜백에 액세스할 수 없지만 알림 이벤트를 사용할 수 있는 것이 가장 좋습니다. 자세한 내용은 사용자 지정 종속성 속성을 참조하세요.