[WPF] Behavior 만들기 – 포커스 하면 TextBox 모든 텍스트 선택하기

[WPF] Behavior 만들기 – 포커스 하면 TextBox 모든 텍스트 선택하기

이번 글에서는 WPF에서 Behavior에 대해 만들어 보겠습니다. Behavior는 WPF에서 MVVM 패턴을 지키면서 UI 컨트롤에 기능을 더해주는 방식으로 .xaml.cs에 정의하는 것이 아닌 View와 ViewModel 사이에서 UI 동작을 중재하는 방식입니다. Behavior에는 핵심적인 동작 3가지가 있습니다.

  • Attach : Behavior가 UI 요소(AssociatedObject)에 연결되는 시점입니다. 여기서 동작할 이벤트를 확인 및 연결 합니다.
  • Action : Behavior에서 작성된 동작이 실행됩니다.
  • Detach : UI 요소가 사라지거나 Behavior가 제거되는 시점입니다. 연결했던 이벤트를 해제합니다.

예를 들어 코드를 만들어 보겠습니다. TextBox를 만들어서 사용할 때 보시면 TextBox에 포커스가 될 때 텍스트가 모두 선택되지 않습니다.

텍스트 박스가 포커스 되면 모든 텍스트가 선택되게 동작하려면 Behavior를 만들어서 해결하면 됩니다. 아래와 같이 TextBoxBehavior를 만들어 줍니다.

public class TextBoxBehavior : Behavior<TextBox>
{
    public TextBoxBehavior()
    {
        
    }
    protected override void OnAttached()
    {
        base.OnAttached();
        
        AssociatedObject.GotKeyboardFocus += OnGotKeyboardFocus; // 키보드 포커스를 받았을 때
        AssociatedObject.PreviewMouseLeftButtonDown += OnPreviewMouseLeftButtonDown; // 마우스 클릭으로 포커스를 받았을 때
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        // 이벤트 연결 해제
        AssociatedObject.GotKeyboardFocus -= OnGotKeyboardFocus;
        AssociatedObject.PreviewMouseLeftButtonDown -= OnPreviewMouseLeftButtonDown;
    }

    private void OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        AssociatedObject.SelectAll(); // 모두 선택
    }

    private void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        // 이미 포커스가 있는 상태에서 클릭한 건 무시
        if (!AssociatedObject.IsKeyboardFocusWithin)
        {
            AssociatedObject.Focus();
            e.Handled = true; // 클릭 이벤트가 텍스트 커서 위치를 바꿔버리는 걸 방지
        }
    }
}

위 코드에서 AssociatedObject는 이 동작을 하는 실제 UI 컨트롤 입니다.
OnAttached 함수에서는 키보드 포커스를 받았을 때 발생하는 이벤트인 GotKeyboardFocus와 마우스 왼쪽 클릭 이벤트인 PreviewMouseLeftButtonDown를 연결해 줍니다.

그리고 OnGotKeyboardFocusOnPreviewMouseLeftButtonDown에서 원하는 동작을 합니다.

OnDetaching 함수에서는 연결된 이벤트를 해제 해줍니다.

MainWindow.xaml에 아래와 같이 TextBox 두 개를 만들어봅니다.

<Window x:Class="WpfBehavior.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfBehavior"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800">
    <StackPanel Orientation="Vertical">
        <!--  일반 TextBox  -->
        <TextBox Margin="5"/>
        
        <!--  Behavior가 장착된 TextBox  -->
        <TextBox Margin="5">
            <i:Interaction.Behaviors>
                <local:TextBoxBehavior/>
            </i:Interaction.Behaviors>
        </TextBox>
    </StackPanel>
</Window>

빌드 후 실행하면 아래와 같이 동작합니다.


github : https://github.com/3001ssw/c_sharp/tree/main/WPF/WPF_Basic/WpfBehavior