C#/WPF

[WPF_Mastereclass] MVVM Binding

HJ0216 2024. 2. 11. 12:40

이 글은 [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

 

 

 

📚 참고 자료

 

INotifyPropertyChanged 인터페이스 (System.ComponentModel)

속성 값이 변경되었음을 클라이언트에 알립니다.

learn.microsoft.com

 

velog

 

velog.io

 

 

C# 바인딩 (onetime, oneway, twoway, onewaytosource)

C#에서 인터페이스에 나타나는 값을 동적으로 표현할때 데이터바인딩을 사용한다. XAML의 내용이 이렇게 선언하면 TEXTBOX안에 표시되는 내용이 ViewModel이라는 뷰모델 클래스의 name이라는 요소와

hihaoun.tistory.com