[WPF] DataBinding(데이터 바인딩)

[WPF] DataBinding(데이터 바인딩)

데이터 바인딩은 WPF 에서 중요한 개념 중 하나로 간단히 말하면 UI와 데이터를 연결해주는 다리라고 생각하면 됩니다. 데이터 바인딩을 하면 UI 속성과 데이터가 연결 되어 자동으로 동기화가 됩니다. 또한 방향도 설정할 수 있어, 데이터 값이 변경되면 UI가 갱신 되게 할 수도 있고, UI가 변경되어서 데이터가 갱신 되게 할 수도 있습니다.

만약 TextBox의 Text 속성에 Value라는 데이터 소스를 바인딩을 할 때 아래와 같이 사용합니다.

<TextBox Text="{Binding Value}" />
<TextBox Text="{Binding Path=Value}"/>

데이터 바인딩 예시

예시를 통해 알아보겠습니다. 프로젝트를 하나 생성한 뒤 MainWindow.xaml에 아래와 같이 입력해줍니다.

<Window x:Class="_05_DataBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        <!--TextBox의 Text가 바인딩 됨-->
        <TextBox x:Name="tbColor" Text="Yellow" Margin="5"/>
        <Label Background="{Binding Text, ElementName=tbColor}" Content="This is Label" Margin="5"/>
    </StackPanel>
</Window>

먼저 실행 화면을 먼저 보겠습니다.

텍스트 박스에 영어로 색상을 입력하면, 라벨의 백그라운드 색상이 변경됩니다. TextBox 요소 이름을 tbColor로 정의 한 뒤, Label의 Background 속성에 tbColor의 텍스트를 바인딩 하였기 때문입니다.

아래는 또 다른 예시입니다.

<Window x:Class="_05_DataBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel>
        <!--TextBox의 Text가 바인딩 됨-->
        <TextBox x:Name="tbColor" Text="Yellow" Margin="5"/>
        <Label Background="{Binding Text, ElementName=tbColor}" Content="This is Label" Margin="5"/>

        <!--slider의 Value가 Binding됨-->
        <Slider x:Name="slider" Minimum="0" Maximum="100" Value="50" Margin="5"/>
        <ProgressBar Value="{Binding Value, ElementName=slider}" Height="30" Margin="5"/>
        <TextBox Text="{Binding Value, ElementName=slider}" Margin="5"/>        
    </StackPanel>
</Window>

위와 같이 입력해서 실행 시키면 아래와 같이 표시됩니다.

슬라이더에 slider라는 이름을 정의 한 뒤 프로그레스바와 텍스트박스에 slider의 Value 속성을 바인딩 했습니다. 그래서 슬라이더를 변경하면 프로그레스바와 텍스트박스가 변경됩니다.

바인딩 방향

두번째 예시에서 텍스트박스에 숫자를 입력하면 슬라이더의 값도 변경하는 것을 볼 수 있습니다. 그 이유는 TextBox의 데이터 바인딩이 양방향(TwoWay)로 되어있기 때문입니다. 양방향으로 되어있다는 것은 Slider의 Value가 TextBox로 동기화되기도 하고, TextBox의 Text가 Slider의 Value로 동기화 된다는 의미입니다.

아래 표는 바인딩 방향에 대한 설명 입니다.

모드방향설명
OneWay소스 → 타겟소스에서 타겟으로만 전달됨
TwoWay소스 ↔ 타겟소스와 타겟이 서로 데이터를 동기화함
OneTime소스 → 타겟 (한 번만)초기 한 번만 소스 데이터를 타겟에 전달, 이후 변경 반영 안 됨
OneWayToSource타겟 → 소스타겟에서 소스로만 데이터가 전달됨 (소스 → 타겟 반영 없음)
Default컨트롤에 따라 다름대부분의 컨트롤은 OneWay, 일부는 TwoWay로 자동 설정됨

위 모드 중에 OneWay 텍스트박스에 설정해보겠습니다.

<!--slider의 Value가 Binding됨-->
<Slider x:Name="slider" Minimum="0" Maximum="100" Value="50" Margin="5"/>
<ProgressBar Value="{Binding Value, ElementName=slider}" Height="30" Margin="5"/>
<TextBox Text="{Binding Value, ElementName=slider, Mode=OneWay}" Margin="5"/>

이렇게 OneWay로 설정하면 소스(Slider의 Value)에서 타겟(TextBox)으로만 전달 되고, 타겟에서 소스로 전달되지는 않습니다.

다른 모드 값도 직접 입력해서 동작하는 것을 보시길 바랍니다.

UpdateSourceTrigger

데이터 바인딩에서 방향도 중요하지만 동기화 되는 시점도 중요합니다. 그 시점을 결정하는 속성이 UpdateSourceTrigger 입니다. TwoWay 모드일 때 TextBox와 Slider의 갱신을 보면 조금 다릅니다. Slider는 변경되면 TextBox에 데이터가 동기화 되는데, TextBox는 포커스를 잃었을 때 Slider에 데이터가 동기화 됩니다.

이 동기화 시점은 UpdateSourceTrigger에서 변경 가능합니다. 아래 표는 UpdateSourceTrigger에 입력하는 값 대한 설명입니다.

UpdateSourceTrigger 값반영 시점설명
Default컨트롤에 따라 다름보통 TextBox.Text는 LostFocus, 다른 컨트롤은 PropertyChanged
PropertyChanged입력 값이 변할 때마다 즉시 반영실시간 데이터 동기화에 적합
LostFocus포커스를 잃을 때 반영TextBox의 기본값
Explicit수동으로만 반영코드에서 BindingExpression.UpdateSource()로 직접 호출해야 함

PropertyChanged는 입력 값이 변할 때마다 즉시 반영하게 해줍니다. 아래와 같이 TextBox에 UpdateSourceTrigger=PropertyChanged를 입력하면 TextBox의 값이 변할 때마다 Slider에 즉시 반영 됩니다.

<!--slider의 Value가 Binding됨-->
<Slider x:Name="slider" Minimum="0" Maximum="100" Value="50" Margin="5"/>
<ProgressBar Value="{Binding Value, ElementName=slider}" Height="30" Margin="5"/>
<TextBox Text="{Binding Value, ElementName=slider, UpdateSourceTrigger=PropertyChanged}" Margin="5"/>

github : https://github.com/3001ssw/c_sharp/tree/main/WPF/WPF_MVVM_1Week/05_DataBinding