사용자 지정 라우트된 이벤트를 만드는 방법(WPF .NET)
WPF(Windows Presentation Foundation) 애플리케이션 개발자 및 구성 요소 작성자는 사용자 지정 라우트된 이벤트를 만들어 CLR(공용 언어 런타임) 이벤트의 기능을 확장할 수 있습니다. 라우트된 이벤트 기능에 대한 자세한 내용은 라우트된 이벤트를 사용하는 이유를 참조하세요. 이 문서에서는 사용자 지정 라우트된 이벤트 만들기의 기본 사항을 설명합니다.
필수 조건
이 문서에서는 독자들이 라우트된 이벤트에 대한 기본 지식을 갖고 있으며 라우트된 이벤트 개요를 읽었다고 가정합니다. XAML(Extensible Application Markup Language)에 익숙하고 WPF(Windows Presentation Foundation) 애플리케이션을 작성하는 방법을 알고 있으면 이 문서의 예제를 따라 하는 데 도움이 됩니다.
라우트된 이벤트 단계
라우트된 이벤트를 만드는 기본 단계는 다음과 같습니다.
RegisterRoutedEvent 메서드를 사용하여 RoutedEvent를 등록합니다.
등록 호출은 등록된 이벤트 이름, 라우팅 전략 및 기타 이벤트 세부 정보가 있는, 라우트된 이벤트 식별자라는
RoutedEvent
인스턴스를 반환합니다. 정적 읽기 전용 필드에 식별자를 할당합니다. 규칙은 다음과 같습니다.CLR 추가 및 제거 이벤트 접근자를 정의합니다. CLR 이벤트 접근자가 없으면 UIElement.AddHandler 및 UIElement.RemoveHandler 메서드에 대한 직접 호출을 통해서만 이벤트 처리기를 추가하거나 제거할 수 있습니다. CLR 이벤트 접근자가 있으면 다음과 같은 이벤트 처리기 할당 메커니즘을 얻을 수 있습니다.
- XAML(Extensible Application Markup Language)의 경우 특성 구문을 사용하여 이벤트 처리기를 추가할 수 있습니다.
- C#의 경우
+=
및-=
연산자를 사용하여 이벤트 처리기를 추가하거나 제거할 수 있습니다. - VB의 경우 AddHandler 및 RemoveHandler 문을 사용하여 이벤트 처리기를 추가하거나 제거할 수 있습니다.
라우트된 이벤트를 트리거하기 위한 사용자 지정 논리를 추가합니다. 예를 들어 논리는 사용자 입력과 애플리케이션 상태에 따라 이벤트를 트리거할 수 있습니다.
예제
다음 예제는 사용자 지정 컨트롤 라이브러리에서 CustomButton
클래스를 구현합니다. Button에서 파생되는 CustomButton
클래스는 다음을 수행합니다.
- RegisterRoutedEvent 메서드를 사용하여
ConditionalClick
이라는 RoutedEvent를 등록하고 등록하는 동안 버블링 전략을 지정합니다. - 등록 호출에서 반환되는
RoutedEvent
인스턴스를ConditionalClickEvent
라는 정적 읽기 전용 필드에 할당합니다. - CLR 추가 및 제거 이벤트 접근자를 정의합니다.
CustomButton
이 클릭되고 외부 조건이 적용될 때 사용자 지정 라우트된 이벤트를 발생시키는 사용자 지정 논리를 추가합니다. 예제 코드는 재정의된OnClick
가상 메서드 내에서ConditionalClick
라우트된 이벤트를 발생시키지만 원하는 방식으로 이벤트를 발생시킬 수 있습니다.
public class CustomButton : Button
{
// Register a custom routed event using the Bubble routing strategy.
public static readonly RoutedEvent ConditionalClickEvent = EventManager.RegisterRoutedEvent(
name: "ConditionalClick",
routingStrategy: RoutingStrategy.Bubble,
handlerType: typeof(RoutedEventHandler),
ownerType: typeof(CustomButton));
// Provide CLR accessors for assigning an event handler.
public event RoutedEventHandler ConditionalClick
{
add { AddHandler(ConditionalClickEvent, value); }
remove { RemoveHandler(ConditionalClickEvent, value); }
}
void RaiseCustomRoutedEvent()
{
// Create a RoutedEventArgs instance.
RoutedEventArgs routedEventArgs = new(routedEvent: ConditionalClickEvent);
// Raise the event, which will bubble up through the element tree.
RaiseEvent(routedEventArgs);
}
// For demo purposes, we use the Click event as a trigger.
protected override void OnClick()
{
// Some condition combined with the Click event will trigger the ConditionalClick event.
if (DateTime.Now > new DateTime())
RaiseCustomRoutedEvent();
// Call the base class OnClick() method so Click event subscribers are notified.
base.OnClick();
}
}
Public Class CustomButton
Inherits Button
' Register a custom routed event with the Bubble routing strategy.
Public Shared ReadOnly ConditionalClickEvent As RoutedEvent = EventManager.RegisterRoutedEvent(
name:="ConditionalClick",
routingStrategy:=RoutingStrategy.Bubble,
handlerType:=GetType(RoutedEventHandler),
ownerType:=GetType(CustomButton))
' Provide CLR accessors to support event handler assignment.
Public Custom Event ConditionalClick As RoutedEventHandler
AddHandler(value As RoutedEventHandler)
[AddHandler](ConditionalClickEvent, value)
End AddHandler
RemoveHandler(value As RoutedEventHandler)
[RemoveHandler](ConditionalClickEvent, value)
End RemoveHandler
RaiseEvent(sender As Object, e As RoutedEventArgs)
[RaiseEvent](e)
End RaiseEvent
End Event
Private Sub RaiseCustomRoutedEvent()
' Create a RoutedEventArgs instance.
Dim routedEventArgs As New RoutedEventArgs(routedEvent:=ConditionalClickEvent)
' Raise the event, which will bubble up through the element tree.
[RaiseEvent](routedEventArgs)
End Sub
' For demo purposes, we use the Click event as a trigger.
Protected Overrides Sub OnClick()
' Some condition combined with the Click event will trigger the ConditionalClick event.
If Date.Now > New DateTime() Then RaiseCustomRoutedEvent()
' Call the base class OnClick() method so Click event subscribers are notified.
MyBase.OnClick()
End Sub
End Class
이 예제에는 XAML 태그를 사용하여 CustomButton
의 인스턴스를 StackPanel에 추가하고 Handler_ConditionalClick
메서드를 CustomButton
및 StackPanel1
요소의 ConditionalClick
이벤트 처리기로 할당하는 별도의 WPF 애플리케이션이 포함되어 있습니다.
<Window x:Class="CodeSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:WpfControl;assembly=WpfControlLibrary"
Title="How to create a custom routed event" Height="100" Width="300">
<StackPanel Name="StackPanel1" custom:CustomButton.ConditionalClick="Handler_ConditionalClick">
<custom:CustomButton
Name="customButton"
ConditionalClick="Handler_ConditionalClick"
Content="Click to trigger a custom routed event"
Background="LightGray">
</custom:CustomButton>
</StackPanel>
</Window>
코드 숨김에서 WPF 애플리케이션은 Handler_ConditionalClick
이벤트 처리기 메서드를 정의합니다. 이벤트 처리기 메서드는 코드 숨김에서만 구현할 수 있습니다.
// The ConditionalClick event handler.
private void Handler_ConditionalClick(object sender, RoutedEventArgs e)
{
string senderName = ((FrameworkElement)sender).Name;
string sourceName = ((FrameworkElement)e.Source).Name;
Debug.WriteLine($"Routed event handler attached to {senderName}, " +
$"triggered by the ConditionalClick routed event raised on {sourceName}.");
}
// Debug output when CustomButton is clicked:
// Routed event handler attached to CustomButton,
// triggered by the ConditionalClick routed event raised on CustomButton.
// Routed event handler attached to StackPanel1,
// triggered by the ConditionalClick routed event raised on CustomButton.
' The ConditionalClick event handler.
Private Sub Handler_ConditionalClick(sender As Object, e As RoutedEventArgs)
Dim sourceName As String = CType(e.Source, FrameworkElement).Name
Dim senderName As String = CType(sender, FrameworkElement).Name
Debug.WriteLine($"Routed event handler attached to {senderName}, " +
$"triggered by the ConditionalClick routed event raised on {sourceName}.")
End Sub
' Debug output when CustomButton is clicked:
' Routed event handler attached to CustomButton,
' triggered by the ConditionalClick routed event raised on CustomButton.
' Routed event handler attached to StackPanel1,
' triggered by the ConditionalClick routed event raised on CustomButton.
CustomButton
을 클릭하는 경우:
ConditionalClick
라우트된 이벤트가CustomButton
에서 발생합니다.CustomButton
에 연결된Handler_ConditionalClick
이벤트 처리기가 트리거됩니다.ConditionalClick
라우트된 이벤트는StackPanel1
까지 요소 트리 위로 트래버스합니다.StackPanel1
에 연결된Handler_ConditionalClick
이벤트 처리기가 트리거됩니다.ConditionalClick
라우트된 이벤트는 요소 트리를 계속 올라가 다른 트래버스된 요소에 연결된 다른ConditionalClick
이벤트 처리기를 트리거할 수 있습니다.
Handler_ConditionalClick
이벤트 처리기는 트리거한 이벤트에 대한 다음 정보를 가져옵니다.
- 이벤트 처리기가 연결된 요소인 보낸 사람 개체.
sender
는 처리기가 처음 실행될 때CustomButton
이 되고 두 번째 실행될 때StackPanel1
이 됩니다. - 원래 이벤트를 발생시킨 RoutedEventArgs.Source 개체 이 예제에서
Source
는 항상CustomButton
입니다.
참고
라우트된 이벤트와 CLR 이벤트의 주요 차이점은 라우트된 이벤트가 요소 트리를 트래버스하여 처리기를 찾는 반면 CLR 이벤트는 요소 트리를 트래버스하지 않으며 처리기는 이벤트를 발생시킨 원본 개체에만 연결할 수 있다는 것입니다. 따라서 라우트된 이벤트 sender
는 요소 트리의 모든 트래버스된 요소일 수 있습니다.
이벤트 등록 호출에서 라우팅 전략을 Tunnel로 설정하는 것을 제외하고 버블링 이벤트와 동일한 방식으로 터널링 이벤트를 만들 수 있습니다. 터널링 이벤트에 대한 자세한 내용은 WPF 입력 이벤트를 참조하세요.
추가 정보
.NET Desktop feedback