프로그래밍/WPF

[WPF] Slider 드래그 완료 시점에 값 업데이트하기

흔한티벳여우 2023. 7. 26. 13:53
반응형

안녕하세요, 오늘은 WPF에서 Slider의 Value를 사용자가 드래그를 완료한 순간에만 업데이트하는 방법에 대해 이야기하려 합니다. 일반적으로 WPF에서는 사용자가 Slider를 드래그하는 동안 실시간으로 값을 업데이트하지만, 이 방법을 사용하면 드래그가 완료된 후에만 업데이트가 이루어집니다.


먼저, 어떤 문제를 해결하려는가?

Slider를 사용하면 사용자는 원하는 값을 직접 조절할 수 있습니다. 이때 Slider의 Value를 어떤 속성에 바인딩하면, 사용자가 슬라이더를 드래그하면서 속성 값이 실시간으로 업데이트됩니다. 이런 실시간 업데이트가 문제가 될 수 있습니다. 왜냐하면 슬라이더를 움직이는 동안에도 바인딩된 속성의 값이 계속 변경되면서 원치 않는 연산이나 UI 업데이트가 발생할 수 있기 때문입니다. 이를 방지하고 사용자가 드래그를 끝낼 때만 속성이 업데이트되게 하려면 어떻게 해야 할까요?

 

해결책: UpdateSourceTrigger 속성과 사용자 지정 Behavior

이 문제를 해결하는 방법은 Binding의 UpdateSourceTrigger 속성을 사용하는 것입니다. 이 속성은 바인딩 소스가 업데이트되는 시점을 결정합니다. 기본적으로는 PropertyChanged가 설정되어 있어서 속성 값이 변경될 때마다 바로 업데이트가 이루어지지만, 이를 Explicit으로 설정하면 프로그램에서 직접 업데이트 시점을 결정할 수 있습니다.

그런데 Slider에서 DragCompleted 이벤트를 처리하려면 어떻게 해야 할까요? 이를 위해 사용자 지정 Behavior를 사용하겠습니다. 이 Behavior는 Slider의 DragCompleted 이벤트를 처리하고 데이터 소스를 업데이트합니다.


사용자 지정 Behavior 작성하기

먼저, 아래와 같이 SliderValueChangedToSourceWhenDragCompletedBehavior라는 사용자 지정 Behavior를 작성해보겠습니다.

public class SliderValueChangedToSourceWhenDragCompletedBehavior : Behavior<Slider>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.AddHandler(Thumb.DragCompletedEvent, new DragCompletedEventHandler(DragCompleted));
    }

    protected override void OnDetaching()
    {
        AssociatedObject.RemoveHandler(Thumb.DragCompletedEvent, new DragCompletedEventHandler(DragCompleted));
        base.OnDetaching();
    }

    private void DragCompleted(object sender, DragCompletedEventArgs e)
    {
        var be = AssociatedObject.GetBindingExpression(Slider.ValueProperty);
        be.UpdateSource();
    }
}


이 Behavior는 Slider에 연결되었을 때 DragCompleted 이벤트 핸들러를 추가하고, 연결이 해제되었을 때 핸들러를 제거합니다. 그리고 이벤트가 발생하면 바인딩 소스를 업데이트합니다.


XAML에서 Behavior 적용하기

이제 XAML에서 이 Behavior를 Slider에 적용해보겠습니다.

<Slider x:Name="mySlider" Minimum="0" Maximum="100">
    <Slider.Value>
        <Binding Path="MyProperty" Mode="TwoWay" UpdateSourceTrigger="Explicit" />
    </Slider.Value>
    <i:Interaction.Behaviors>
        <local:SliderValueChangedToSourceWhenDragCompletedBehavior />
    </i:Interaction.Behaviors>
</Slider>


이 경우, i:는 xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 입니다., local:은 사용자가 정의한 Behavior가 있는 네임스페이스를 나타냅니다. 이를 적절하게 설정해야 합니다.


마무리

이렇게 하면 사용자가 슬라이더를 움직일 때 바인딩된 속성은 업데이트되지 않다가, 사용자가 움직임을 멈추면 해당 속성이 업데이트됩니다. 그리고 이 모든 것이 XAML과 사용자 지정 Behavior 내에서 처리되므로, 뷰의 코드 비하인드에는 코드가 없습니다. 이를 통해 코드의 분리와 재사용성을 높일 수 있습니다.

다음에는 다른 고급 WPF 기능에 대해 더 깊게 들어가 보겠습니다. 감사합니다!

반응형