티스토리 뷰

IT/C#

[WPF] RoutedEvent 선언 및 이벤트 호출

주인장 진빼이

RoutedEvent란?

CustomControl 또는 UserControl을 만들려고할 때

커스텀 이벤트가 필요한 경우나 또는 상속받은 컨트롤에 대한 이벤트를 처리할 필요가 종종있다.

RoutedEvent를 통해 Control에 대한 이벤트를 처리할 수 있다.

 

RoutedEvent라는 말이 어렵다면.. 의존성 속성에 등록된 이벤트라고 생각하면 더 쉽게 받아질지도 모르겠다.

 

흔히 볼 수 있는 컨트롤인 버튼에 사용되는 Click, MouseDown 이벤트등은 RoutedEvent의 예시중 일부이다.

 

RoutedEvent는 3가지 방식이 있다.(터널링, 버블링, 직접)

어려워보일 수 있지만 진짜 쉽게 이해할 수 있다.

 

Click이벤트가 호출되었다고 가정해보자

이때 클릭 이벤트가 어디가 우선적으로 처리될 건지에 따라 방식이 달라진다.

터널링: (터널이니까 안에 점점 들어간다고 생각하자, 터널의 입구점은 루트라 생각하면 더 쉽게 와닿는다) 루트 요소에서 클릭했던 요소까지 순차적인 이벤트가 처리되는 방식이다. 터널링 이벤트는 접두사로 Preview가 붙는다.

버블링: (올라간다고 생각하자) 클릭된 요소(Source)에서 루트요소까지 순차적인 이벤트가 처리되는 방식

직접: 버블링과 터널링은 시작된 요소에서 끝 요소까지 이벤트가 순차적으로 처리되지만, 직접은 클릭했던 요소만 처리하는 방식을 말한다.

 

RoutedEvent는 순차적으로 이벤트가 처리되는데 중간에 끊고 싶다면

RoutedEventArgs 개체에서 Handled를 true로 설정하면 진행되는 이벤트가 중간에 끊기게 된다.

컨트롤이 겹쳐진게 10개가 있다고 할 때

5번째 이벤트를 처리할 때 Handled 속성 값을 true로 설정했을 경우 나머지 6,7,8,9,10 이벤트를 처리되지 않는 것이다.

 

 

코드를 통해 알아보자

RoutedEvent 선언하기

RoutedEvent를 선언하기 위해서는 EventManager 객체에 정적함수인 RegisterRoutedEvent를 통해 만들어야 한다.

등록된 RoutedEvent는 식별할 수 있게 이름을 가지게 된다.

 

RoutedEvent 클래스를 보면 알다시피

함수를 통해 등록한 정보가 그대로 ChangedFilterEvent 변수에 들어간다고 생각하면 된다.

public sealed class RoutedEvent
{
        public string Name { get; }
        public Type OwnerType { get; }
        public RoutedEvent AddOwner(Type ownerType);
        public override string ToString();
}

 

 

등록한 이벤트명은 xaml에서 핸들러로 처리할 수도 있다.

 

/*
public static RoutedEvent RegisterRoutedEvent(string name, RoutingStrategy routingStrategy, Type handlerType, Type ownerType);
public static readonly RoutedEvent ChangedFilterEvent = EventManager.RegisterRoutedEvent("이벤트명", 사용할방식, typeof(핸들러타입), typeof(이벤트주인타입));
*/
public static readonly RoutedEvent ChangedFilterEvent = EventManager.RegisterRoutedEvent("ChangedFilter", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(FilterDataGrid));

 

무조건 지켜야할 네이밍은 아니지만 RoutedEvent타입을 가진 변수이름에 "Event"를 접미사로 사용하자

(변수 네이밍은 언제나 어렵다)

 

RoutedEvent 핸들러 등록하기

CustomControl 내 아래 코드를 사용하여 핸들러를 등록할 수 있다.

public event RoutedEventHandler ChangedFilter
{
  add { AddHandler(ChangedFilterEvent, value); }
  remove { RemoveHandler(ChangedFilterEvent, value); }
}

 

ChangedFilterEvent는 이벤트를 등록한 정보,

ChangedFilter는 이벤트 핸들러 정보들을 가지고 있다.

핸들러란 쉽게 말해. 이벤트를 처리하는 델리게이트이다.

 

등록한 이벤트 호출하기

예를 들어 사용자가 필터를 변경했을 때 (보여지는 아이템의 정보가 설정한 필터정보에 의해 변경되었을 때)

내부적으로 이벤트를 호출하여 시작을 알려야한다.

 

다른 곳에서 이벤트핸들러를 추가했다면 체인식으로 호출될 것이다. (무조건 체인방식은 아니다)

 

이벤트는 기본적으로 RaiseEvent 함수를 사용하여 호출한다.

등록한 이벤트에 RoutedEvent에 대한 Args 정보를 등록했었다. (당연히 호출시 해당 타입의 Args를 매개변수로 넘겨줘야 한다)

RoutedEventArgs args = new RoutedEventArgs(FilterDataGrid.ChangedFilterEvent);
RaiseEvent(args);

 

추가로 인자를 넣어 원하는 데이터를 넘겨줄 수도 있다.

EventTrigger & CallMethodAction

내부적으로 이벤트를 등록 및 호출했으니 ViewModel에서 해당 이벤트를 처리할 수 있게도 만들어보자

EventTrigger를 이용하여 처리한다. 이벤트를 처리하는 함수이니까 함수 이름은 On으로 시작하게 적어주도록 하자.

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
      
<i:EventTrigger EventName="ChangedFilter">
	<ei:CallMethodAction TargetObject="{Binding}" MethodName="OnFilterChanged"/>
</i:EventTrigger>

ViewModel에서 이벤트 처리하기

이제 ViewModel에서 OnFilterChanged 함수를 정의하자.

디버거로 찍어보면 알겠지만 모든 정보가 잘 들어오는 것을 확인할 수 있다.

sender는 이벤트가 등록되었던 객체에 대한 정보가 들어온다.

public void OnFilterChanged(object sender, RoutedEventArgs e)
{

}

 

 

아주 간단하게 RoutedEvent에 대해 알아보았다. 아직도 부족한 것이 많다.

xaml을 더 연습하도록 하자.

 

MVVM 프레임워크는 MVVMLight를 사용했다.

 

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함