Version: 2019.3
언어: 한국어
이벤트 디스패치
드래그 앤 드롭 지원

이벤트 응답

다음의 두 가지 방법으로 시각적 요소가 수신하는 이벤트에 대해 응답하도록 만들 수 있습니다.

  • 이벤트 콜백 등록
  • 기본 액션 구현

이벤트 콜백을 등록해야 하는지, 아니면 기본 액션을 구현하는지 여부를 결정하는 요소는 많습니다.

예를 들어 기존 클래스의 오브젝트를 인스턴스화하고 있고 해당 인스턴스가 이벤트를 수신할 때 특정한 방식으로 응답하도록 만들고 싶은 경우에는 이 인스턴스에 콜백을 등록하는 것 외에 다른 방법은 없습니다.

하지만 VisualElement에서 새로운 클래스를 파생하고 이 클래스의 모든 인스턴스가 이벤트에 대해 동일하게 응답하도록 만들고 싶은 경우 생성자에서 이 클래스의 모든 인스턴스에 콜백을 등록하거나, 해당 클래스에 대해 기본 액션을 구현할 수 있습니다.

콜백과 기본 액션 간의 근본적인 차이는 다음과 같습니다.

  • 콜백은 클래스의 인스턴스에 등록해야 합니다. 기본 액션은 클래스에서 가상 함수로 구현됩니다.
  • 콜백은 전파 경로를 따라 모든 요소에 대해 실행됩니다. 기본 액션은 이벤트 타겟에 대해서만 실행됩니다.

event.PreventDefault()를 호출하여 기본 액션이 실행되지 않도록 만들 수 있습니다. 일부 이벤트 타입은 취소가 불가능합니다. 즉, 해당 기본 액션은 취소할 수 없습니다. 취소할 수 없는 이벤트라도 event.StopPropagation() 또는 event.StopImmediatePropagation()을 호출하여 콜백이 실행되지 않도록 만들 수 있습니다.

기본 동작은 특정 타입의 요소가 이벤트를 수신할 때 포함해야 하는 동작으로 간주해야 합니다.

예를 들어 체크박스는 상태를 토글하여 클릭 이벤트에 응답해야 합니다. 또한 이 동작은 모든 체크박스에 콜백을 등록하는 대신, 기본 액션 가상 함수를 오버라이드하여 구현해야 합니다.

일반적으로는 기본 액션을 사용하여 요소에서 자연스럽게 예상되는 동작을 구현하는 것이 좋습니다. 이렇게 하면 인스턴스에 연결된 콜백에서 PreventDefault()를 호출하여 인스턴스 기반으로 기본 요소 동작을 취소할 수 있습니다.

동작을 기본 액션으로 구현할 경우 얻을 수 있는 추가 혜택으로는 콜백 레지스트리에서 룩업하지 않고도 실행할 수 있다는 점과 콜백이 없는 인스턴스가 트리클다운/버블업(trickle down/bubble up) 전파 프로세스를 통해 최적화된다는 점을 들 수 있습니다.

유연성 향상을 위해 이벤트 타겟의 기본 액션을 이벤트 디스패치 프로세스 동안 두 지점에서 실행할 수 있습니다.

  • ExecuteDefaultActionsAtTarget();를 오버라이드한 후 트리클다운 및 버블업 전파 단계 사이 그리고 타겟 콜백이 실행된 직후.
  • ExecuteDefaultActions()`를 오버라이드한 후 이벤트 디스패치 프로세스의 끝.

가능하면 ExecuteDefaultActions()에서 클래스 기본 액션을 구현하십시오. 이렇게 하면 클래스의 사용자가 더 많은 오버라이드 옵션을 이용할 수 있으며, 이벤트 전파 프로세스의 트리클다운 단계 또는 버블업 단계 동안 PreventDefault()를 호출할 수 있습니다.

하지만 때때로 클래스에 대한 기본 액션을 실행하는 이벤트가 요소의 부모에 전파되지 않도록 해야 합니다. 예를 들어 텍스트 필드는 값을 수정하는 키 다운 이벤트를 수신합니다. 이 키 다운 이벤트는 Delete 키를 사용하여 콘텐츠를 삭제할 수 있는 부모에는 전파되지 않습니다. 이 경우 ExecuteDefaultActionsAtTarget()을 사용하여 기본 액션을 구현하고 StopPropagation()을 호출하십시오. 이렇게 하면 이벤트가 버블업 단계 동안 콜백에 의해 처리되지 않습니다.

기본 액션은 이벤트의 타겟에 대해서만 실행됩니다. 요소가 이벤트 전파 프로세스의 결과로 이벤트를 수신할 때에는 실행되지 않습니다. 클래스가 자식 또는 부모에서 타겟팅된 이벤트에 대해 응답하도록 만들고 싶으면 클래스의 각 인스턴스에 콜백을 등록해야 합니다. 이러한 작업은 때때로 필요하지만, 보다 뛰어난 확장성과 성능을 위해서는 클래스의 모든 인스턴스에 콜백을 등록하지 않는 것이 좋습니다.

이벤트 콜백 등록

시각적 요소의 특정 인스턴스에 커스텀 동작을 추가하려면 커스텀 동작을 트리거하는 이벤트에 대한 콜백을 등록해야 합니다.

이벤트 콜백을 등록할 경우 기존 클래스의 개별 인스턴스 동작을 커스터마이즈할 수 있는 장점이 있습니다. 이벤트 콜백을 등록할 경우의 단점으로는 실행 시간이 오래 걸려서 성능적 제한이 있다는 점을 들 수 있습니다. 이벤트가 수신될 때마다 등록된 이벤트를 확인하여 어느 콜백을 실행할지 판단해야 하기 때문에 실행 시간이 오래 걸립니다.

예를 들어 다음 코드는 MouseDownEvent에 대한 두 개의 콜백을 등록합니다.

    // Register a callback on a mouse down event
        myElement.RegisterCallback<MouseDownEvent>(MyCallback);
        // Same, but also send some user data to the callback
        myElement.RegisterCallback<MouseDownEvent, MyType>(MyCallbackWithData, myData);

콜백 서명은 다음과 같은 모습입니다.

void MyCallback(MouseDownEvent evt) { /* ... */ }
void MyCallbackWithData(MouseDownEvent evt, MyType data) { /* ... */ }

이벤트에 대해 가능한 많은 콜백을 등록할 수 있습니다. 하지만 콜백 등록 시스템은 특정 이벤트 및 전파 단계에서 두 번 이상 동일한 콜백 함수를 등록하는 것을 허용하지 않습니다. myElement.UnregisterCallback() 메서드를 호출하여 VisualElement에서 콜백을 제거할 수 있습니다.

타겟을 제외하고, 전파 경로에 있는 각 요소는 이벤트를 두 번씩, 즉 트리클다운 단계에서 한 번, 버블업 단계에서 한 번 수신합니다. 등록된 콜백이 두 번씩 실행되지 않도록 하려면 RegisterCallback(옵션)을 사용하여 콜백이 실행되는 단계를 지정하십시오.

기본적으로, 등록된 콜백은 타겟 단계 그리고 버블업 단계 동안 실행됩니다. 이러한 기본 동작은 부모 요소가 자식 이후에 반응하도록 해줍니다. 예를 들어 부모가 먼저 반응하도록 만들고 해당 자식의 동작을 오버라이드하려면 TrickleDown.TrickleDown 옵션을 사용하여 콜백을 등록해야 합니다.

    // Register a callback for the trickle down phase
        myElement.RegisterCallback<MouseDownEvent>(MyCallback, TrickleDown.TrickleDown);

이는 디스패처에 타겟 단계와 트리클다운 단계에서 콜백을 실행하라고 알립니다.

기본 액션 구현

기본 액션은 클래스의 모든 인스턴스에 적용됩니다. 즉, 하나 또는 두 개 모두의 메서드가 요소가 수신하는 모든 이벤트에 대해 호출됩니다.

기본 액션을 구현하는 클래스는 해당 인스턴스에 등록된 콜백도 보유할 수 있습니다.

이벤트 클래스는 이벤트를 처리하기 이전 또는 이후에 실행되는 동작을 구현합니다. 이벤트 클래스는 EventBase 클래스에 있는 PostDispatch() 메서드의 PreDispatch()를 오버라이드하여 이 작업을 수행합니다. 이벤트는 대기열에 들어가므로, 이러한 메서드는 이벤트가 방출될 때가 아니라 이벤트가 처리될 때 상태를 업데이트하거나 작업을 수행할 수 있습니다. 예를 들어 BlurEvent는 요소를 처리하기 전에 현재 포커스가 있는 요소를 변경합니다.

기본 액션을 구현하려면 VisualElement의 새로운 서브 클래스를 파생하고. ExecuteDefaultActionAtTarget() 메서드 또는 ExecuteDefaultAction() 메서드, 또는 두 메서드 모두를 구현해야 합니다.

기본 액션은 이벤트를 수신할 때 시각적 요소 서브 클래스의 각 인스턴스에서 실행되는 액션입니다. ExecuteDefaultActionAtTarget()ExecuteDefaultAction()을 오버라이드하여 기본 액션을 커스터마이즈할 수 있습니다.

override void ExecuteDefaultActionAtTarget(EventBase evt)
{
    // Do not forget to call the base function.
    base.ExecuteDefaultActionAtTarget(evt);

    if (evt.GetEventTypeId() == MouseDownEvent.TypeId())
    {
        // ...
    }
    else if (evt.GetEventTypeId() == MouseUpEvent.TypeId())
    {
        // ...
    }
    // More event types
}

유연성 향상을 위해 ExecuteDefaultAction()에서 기본 액션을 구현하는 것이 좋습니다. 그렇게 하면 사용자가 필요할 경우 기본 액션의 실행을 중지하거나 막을 수 있습니다.

타겟 기본 액션이 부모 콜백 전에 실행되도록 만들고 싶으면 ExecuteDefaultActionAtTarget()에서 기본 액션을 구현하십시오.

이벤트 처리 시퀀스

이벤트가 발생하면 이벤트는 시각적 요소 트리에서 전파 경로를 따라 전송됩니다. 이벤트 타입이 이벤트 전파의 모든 단계를 따를 것을 요구한다고 가정하고 이벤트가 각 시각적 요소로 전송됩니다. 이벤트 처리 시퀀스는 다음과 같습니다.

  1. 루트 요소에서 이벤트 타겟의 부모까지 요소에 대한 이벤트 콜백을 실행합니다. 이는 디스패치 프로세스의 트리클다운 단계입니다.
  2. 이벤트 타겟에 대한 이벤트 콜백을 실행합니다. 이는 디스패치 프로세스의 타겟 단계입니다.
  3. 타겟 ExecuteDefaultActionAtTarget()을 호출합니다.
  4. 이벤트 타겟 부모에서 루트까지 요소에 대한 이벤트 콜백을 실행합니다. 이는 디스패치 프로세스의 버블업 단계입니다.
  5. 타겟 ExecuteDefaultAction()을 호출합니다.

이벤트가 전파 경로를 따라 전송되면 Event.currentTarget이 현재 이벤트를 처리 중인 요소로 업데이트됩니다. 즉, 이벤트 콜백 함수 내에서 Event.currentTarget은 콜백이 등록되는 요소이고 Event.target은 이벤트가 발생하는 요소입니다.

이벤트 전파 중지 및 기본 액션 취소

콜백을 사용하여 실행 중인 액션을 중단, 방지 및 취소할 수 있습니다. 하지만 EventBase.PreDispatch()EventBase.PostDispatch() 메서드의 실행은 막을 수 없습니다.

다음 메서드는 이벤트 전파와 기본 액션에 영향을 미칩니다.

  • StopImmediatePropagation()은 이벤트 전파 프로세스를 즉시 중단합니다. 다른 콜백이 이 이벤트에 대해 실행되지 않습니다. 하지만 ExecuteDefaultActionAtTarget()ExecuteDefaultAction() 기본 액션은 여전히 실행됩니다.
  • StopPropagation()은 현재 요소에 대한 마지막 콜백 이후 이벤트 전파 프로세스를 중단합니다. 이는 모든 콜백이 현재 요소에 대해 실행되고 다른 추가 요소가 이벤트에 응답하지 않도록 만들기 위함입니다. ExecuteDefaultActionAtTarget()ExecuteDefaultAction() 기본 액션은 여전히 실행됩니다.
  • PreventDefaultAction()ExecuteDefaultActionAtTarget()ExecuteDefaultAction() 기본 액션이 호출되지 않도록 만듭니다. PreventDefaultAction()은 다른 콜백의 실행을 막지 않습니다. 또한 버블업 단계 동안 PreventDefaultAction()을 호출하면 ExecuteDefaultActionAtTarget() 기본 액션이 방지됩니다. 이는 해당 액션이 이미 실행되었기 때문입니다. ExecuteDefaultActionAtTarget() 기본 액션은 트리클다운 단계 동안 실행됩니다.

  • 2018–11–02 페이지 수정됨
이벤트 디스패치
드래그 앤 드롭 지원