728x90
1. UI와 데이터 간 바인딩
- 바인딩은 클래스와 클래스간의 속성을 연결시키는 작업이고, 컨트롤 또한 하나의 클래스이기 때문에 바인딩 작업이 가능하다.
- WPF 어플리케이션을 개발하면서 가장 많이 바인딩 하는 경우는 CS 파일 등에서 정의된 데이터 형의 클래스와 컨트롤을 연결할 때 인데, 예를들어 사람의 인적 사항을 정의하는 클래스에 이름이라는 속성을 TextBox 에 Text 속성에 바인딩하여 자동으로 TextBox에 사람의 이름이 표시되도록 하는 방식이다.
- ECDIS 에서 특히 자주 사용되며, 수많은 ECDIS에 세부 설정들은 그 종류에 따라서 개별 클래스로 정의가 되어 있다.
→ UI와 클래스를 바인딩하여 별도의 이벤트 처리 없이 자동으로 UI와 내부 데이터가 변경되도록 처리하는 방식
2. 예제 UI만들기
- 인적사항을 표시하거나 설정하는 예제 만들기
(1) UI 만들기
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="Window"
SizeToContent="WidthAndHeight"
>
<Grid Height="180" Width="180">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="Name" Margin="3" VerticalAlignment="Center" />
<TextBlock Grid.Column="0" Grid.Row="1" Text="Age" Margin="3" VerticalAlignment="Center" />
<TextBlock Grid.Column="0" Grid.Row="2" Text="Address" Margin="3" VerticalAlignment="Center" />
<TextBlock Grid.Column="0" Grid.Row="3" Text="Job" Margin="3" VerticalAlignment="Center" />
<TextBlock Grid.Column="0" Grid.Row="4" Text="Marrued" Margin="3" VerticalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="0" Margin="3" />
<ComboBox Grid.Column="1" Grid.Row="1" Margin="3" >
<ComboBoxItem>20~30</ComboBoxItem>
<ComboBoxItem>30~40</ComboBoxItem>
<ComboBoxItem>40~50</ComboBoxItem>
<ComboBoxItem>50~</ComboBoxItem>
</ComboBox>
<TextBox Grid.Column="1" Grid.Row="2" Margin="3" />
<ComboBox Grid.Column="1" Grid.Row="3" Margin="3">
<ComboBoxItem>Engineer</ComboBoxItem>
<ComboBoxItem>Teacher</ComboBoxItem>
<ComboBoxItem>Doctor</ComboBoxItem>
</ComboBox>
<CheckBox Grid.Column="1" Grid.Row="4" Margin="3" VerticalAlignment="Center"/>
<Button Grid.Column="1" Grid.Row="5" Content="Save" Margin="3" VerticalAlignment="Center"/>
</Grid>
</Window>
(2) 바인딩 할 클래스 만들기
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class PersonInfo
{
private string name = null;
private string address = null;
private int age = 0;
private int job = 0;
private bool married = false;
public string Name
{
get { return name; }
set { name = value; }
}
public string Address
{
get { return address; }
set { address = value; }
}
public int Age
{
get { return age; }
set { age = value; }
}
public int Job
{
get { return job; }
set { job = value; }
}
public bool Married
{
get { return married; }
set { married = value; }
}
}
}
(3) 클래스 객체 만들기
- 바인딩은 클래스 속성간의 연결이므로 객체를 만든 후 이를 이용해서 별도로 작성한 클래스 형의 속성을 get, set을 이용해 만들어줘야한다.
public partial class MainWindow : Window
{
private PersonInfo person = new PersonInfo();
public PersonInfo Person
{
get { return person; }
set { person = value; }
}
public MainWindow()
{
InitializeComponent();
}
}
...
→ 객체를 따로 만들고 이를 이용해 속성을 만들었다.
객체를 만들지 않고 속성만 public PersonInfo Person {get; set;} 과 같은 방식으로 만들어도 무방하다.
(4) 바인딩 작업
- CS 파일에 정의된 속성에 정의한 속성은 MainWindow 에 포함되어 있으니 XAML에서 Window 태그에 Name속성을 정의해서 접근하면된다.
- Window에 Name을 지정하면, 바인딩시에 ElementName을 지정된 이름으로 설정하고 Path를 작업한 클래스형의 속성으로 해주면 된다.
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="Window"
SizeToContent="WidthAndHeight" Name="mainWindow"
>
- 바인딩을 걸 때 ElementName은 앞서 설정한 Window태그 이름은 window로 설정하고 path는 윈도우 클래스인 MainWindow에서 만들어준 Person 속성으로 지정하는데, 우리는 여기서 person 속성 하위의 name이라는 속성을 표시해야하므로 Person.Name 과 같은 형식으로 path를 지정해준다.
위와 같은 형식을 매번 반복하지 않도록 DataContext를 사용하여 특정 컨트롤 하위에서 사용할 기본 속성을 지정 해 준다.
...
<Grid Height="180" Width="180" DataContext="{Binding ElementName=mainWindow, Path=Person}">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
...
- PersonInfo 클래스에서 정의한 각종 속성의 데이터형과 바인딩 할 컨트롤의 속성 데이터형은 동일해야한다. int, bool과 같은 형태가 아니라 XAML코드 상에서 표시되는 최종적인 형태가 중요하다.
만약 형태가 다른 데이터를 바인딩 해야 한다면, 컨버터를 만들어 사용한다.
...
<TextBlock Grid.Column="0" Grid.Row="0"
Text="Name" Margin="3" VerticalAlignment="Center" />
<TextBlock Grid.Column="0" Grid.Row="1"
Text="Age" Margin="3" VerticalAlignment="Center" />
<TextBlock Grid.Column="0" Grid.Row="2" Text="Address" Margin="3" VerticalAlignment="Center" />
<TextBlock Grid.Column="0" Grid.Row="3" Text="Job" Margin="3" VerticalAlignment="Center" />
<TextBlock Grid.Column="0" Grid.Row="4" Text="Married" Margin="3" VerticalAlignment="Center" />
<TextBox Grid.Column="1" Grid.Row="0"
Text="{Binding Path=Name}" Margin="3" />
<ComboBox Grid.Column="1" Grid.Row="1"
SelectedIndex="{Binding Path=Age}" Margin="3" >
<ComboBoxItem>20~30</ComboBoxItem>
<ComboBoxItem>30~40</ComboBoxItem>
<ComboBoxItem>40~50</ComboBoxItem>
<ComboBoxItem>50~</ComboBoxItem>
</ComboBox>
<TextBox Grid.Column="1" Grid.Row="2"
Text="{Binding Path=Address}" Margin="3" />
<ComboBox Grid.Column="1" Grid.Row="3"
SelectedIndex="{Binding Path=Job}" Margin="3">
<ComboBoxItem>Engineer</ComboBoxItem>
<ComboBoxItem>Teacher</ComboBoxItem>
<ComboBoxItem>Doctor</ComboBoxItem>
</ComboBox>
<CheckBox Grid.Column="1" Grid.Row="4" Margin="3"
IsChecked="{Binding Path=Married}" VerticalAlignment="Center"/>
<Button Grid.Column="1" Grid.Row="5" Content="Save" Margin="3" VerticalAlignment="Center" Click="Button_Click"/>
</Grid>
</Window>
(5) 바인딩 결과 갱신버튼 추가
- UI수정
...
<CheckBox Grid.Column="1" Grid.Row="4" Margin="3"
IsChecked="{Binding Path=Married}" VerticalAlignment="Center"/>
<Button Grid.Column="0" Grid.Row="5" Content="change" Margin="3" VerticalAlignment="Center" Click="Button_Click_1"/>
<Button Grid.Column="1" Grid.Row="5" Content="Save" Margin="3" VerticalAlignment="Center" Click="Button_Click"/>
</Grid>
- CS 파일 수정
...
private void Button_Click_1(object sender, RoutedEventArgs e)
{
person.Name = "Lee";
person.Age = 3;
person.Address = "Mangpo";
person.Job = 2;
person.Married = false;
}
}
→ change 버튼을 누르면 아무 변화가 없지만 save 버튼을 누르면 임의로 변경한 값이 반영되어 나온다.
즉, 내부 데이터는 변경되었지만 UI에서만 변경이 되지 않은 것.
- WPF는 C#에서 사용하는 일반적인 방식으로 속성을 만들면 실행할 때, 초기 데이터는 반영을 하지만 중간에 속성이 변경되면 반영이 되지 않는다.
개별 속성 별로 그 속성이 변경되었다는 이벤트를 발생시켜 내부적으로 속성이 변경되었다는 것을 알려줘야만 바인딩을 했을 때에도 바로 반영이 된다.
3. 속성 변경 이벤트
- INotifyPropertyChanged 인터페이스를 상속 받는다.
INotifyPropertyChanged를 사용하기 위해서는 System.ComponentMode 네임스페이스를 추가해준다.
- INotifyPropertyChanged 라는 인터페이스를 상속 받은 후 클래스 내부에 이벤트 함수를 만들어준다. 이 이벤트 함수를 각각의 속성이 변경 될 때 마다 발생시켜서 WPF상에서 바인딩 된 데이터가 변경되는 것을 알릴 수 있도록 해야한다.
...
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged(string name)
{
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
- 이벤트 함수를 작성했으면 클래스 내 각 송성마다 모두 값이 변경되는 set 부분에서 이벤트를 발생시킨다. 이벤트 파라미터는 그 속성의 이름으로 한다. 모든 속성에 대해 이벤트 메서드를 추가해주고 실행 해 보면 속성이 변경 될 떄 바인딩된 UI도 바로 변경이 된다.
728x90
'C# > C# WPF 개념' 카테고리의 다른 글
[C# WPF] 참고 사이트 모음 (0) | 2023.08.17 |
---|---|
[C# WPF] 바인딩 #04 - 목록 기반의 컨트롤 바인딩 (0) | 2023.08.17 |
[C# WPF] 바인딩 #03 - 컨버터 확장 (0) | 2023.08.17 |
[C# WPF] 바인딩 #02 - 컨버터 (0) | 2023.08.17 |
[C# WPF] 바인딩 #01 - 바인딩의 개념 (0) | 2023.08.17 |