[WPF_Mastereclass] MVVM Binding
이 글은 [WPF_Mastereclass]을 수강하며 정리한 글입니다.
👉 기본 환경
- Language: C#, xaml
- IDE: Visual Basic 2022
ViewModel
namespace WeatherApp.ViewModels
{
public class WeatherVM : INotifyPropertyChanged
{
private string _query;
public string Query
{
get { return _query; }
set
{
_query = value;
OnPropertyChanged("Query");
}
}
private CurrentConditions _currentConditions;
public CurrentConditions CurrentConditions
{
get { return _currentConditions; }
set
{
_currentConditions = value;
OnPropertyChanged("CurrentConditions");
}
}
private City _selectedCity;
public City SelectedCity
{
get { return _selectedCity; }
set
{
_selectedCity = value;
OnPropertyChanged("SelectedCity");
}
}
public WeatherVM()
{
if(DesignerProperties.GetIsInDesignMode(new System.Windows.DependencyObject()))
{
SelectedCity = new City
{
LocalizedName = "Seoul"
};
CurrentConditions = new CurrentConditions
{
WeatherText = "Clear",
Temperature = new Temperature
{
Metric = new Units
{
Value = 0
}
}
};
}
}
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
INotifyPropertyChanged
- 클라이언트(일반적으로 바인딩 클라이언트)에게 속성 값이 변경되었음을 알리는 데 사용
PropertyChanged
- 속성값이 변경될 때, 발생하는 Event
OnPropertyChanged
- 속성값이 변경될 때, 속성 이름을 OnPropertyChanged를 매개변수로 건내면
→ Binding된 UI 컴포넌트에 속성값의 변경을 안내
Model
<Window x:Class="WeatherApp.Views.WeathereWindow"
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:WeatherApp.Views"
xmlns:vm="clr-namespace:WeatherApp.ViewModels"
mc:Ignorable="d"
Title="WeathereWindow" Height="600" Width="400">
<Window.Resources>
<vm:WeatherVM x:Key="weatherVM"/>
</Window.Resources>
</Window>
xmlns
- XML Name Space 선언
- XML에서의 import 기능
Window.Resources
- 리소스를 정의하고 참조
<Grid DataContext="{StaticResource weatherVM}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Margin="20">
<TextBlock Text="Search for a city!"/>
<TextBox
Text="{Binding Query, Mode=TwoWay}"
/>
<Button
Margin="0 10"
Content="Search"
/>
<ListView>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</Grid>
<Grid DataContext="{StaticResource weatherVM}">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid
Grid.Row="1"
Background="#4392F1"
DataContext="{Binding CurrentConditions}"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Margin="0 10">
<TextBlock
DataContext="{StaticResource weatherVM}"
Margin="20 0"
Foreground="#F4F4F8"
FontSize="20"
Text="{Binding SelectedCity.LocalizedName}"
/>
<TextBlock
Margin="20 0"
Foreground="#F4F4F8"
FontSize="18"
Text="{Binding WeatherText}"
/>
</StackPanel>
<TextBlock
Grid.Column="1"
Margin="20 0"
Foreground="#F4F4F8"
VerticalAlignment="Center"
FontSize="30"
Text="{Binding Temperature.Metric.Value, StringFormat={}{0}℃}"
/>
</Grid>
</Grid>
DataContext
- 해당 UI 컴포넌트에서 사용할
- Resource로 선언한 VM에서 선택
- 계층 구조
- Grid의 StaticResource가 weatherVM으로 선언될 때,
Grid 안의 SpackPanel 안의 Textbox는 weatherVM 안의 데이터(Query)로 접근
* 만일 하위 UI 컴포넌트에서 상위 UI 컴포넌트와 다른 바인딩을 하고자 할 경우, DataContext 재선언
<TextBox
Text="{Binding Query, Mode=TwoWay}"
/>
Mode
- OneWay: ViewModel → VIew
- OneTime: ViewModel → VIew, 한 번만 연결
- OneWayToSource: View → VIew Model
- TwoWay: ViewModel ↔ VIew
📚 참고 자료