본문 바로가기
wpf/wpf mvvm패턴을 활용한 환율계산기

wpf MVVM패턴을 활용한 간단한 환율계산기 만들기

by devjh 2020. 10. 2.
반응형

이번게시글에서는 MVVM패턴을 활용한 환율계산기를 포스팅하겠습니다.

 

먼저 MVVM 패턴에 대해 알아보겠습니다.

 

MVVM패턴이란

Model-View-ViewModel의 약자로
웹개발에서 흔히 사용하는 MVC패턴에서 컨트롤러 대신 ViewModel을 사용하는 패턴입니다.
MVC패턴은 Controller로 API로 요청이 들어오지만
MVVM패턴은 View의 클릭이벤트로 ViewModel로 요청이 들어옵니다. 
View와 ViewModel 사이의 의존성을 없앴다는 장점이 있습니다.

 

각각의 역할

View - 사용자의 눈에 보이는 UI를 담당하는 곳
Model - 데이터 처리(FILEIO나 DB를 사용해 데이터를 저장하는곳)
ViewModel - View를 표현하기 위한 Model로 VIew에서 들어온 데이터를 가공하며 Model과의 통신한후 View단과의 Binding을 통해 데이터를 자동으로 갱신시켜 주는곳

 

동작순서

1. 사용자의 입력은 VIew를 통해 들어옵니다.
2. View에서 들어온 데이터는 VIewModel에 전달되며 ViewModel은 Model과의 데이터 교환을 합니다.(Model에서는 DB나 FILEIO처리 등 VIEW와 상관없는 로직을 처리하곤 합니다.)
3. 데이터 교환 이후 ViewModel에서 가공, 처리한후 Data Binding을 통해 View를 갱신합니다.

 

직접 환율계산기를 만들면서 확인해보겠습니다.

1. 결과화면

 

 

dollar에 숫자를 입력하면 현재환율(2020.10.02 기준 1달러는 1160원)을 기준으로

 

won을 출력해주는 예제입니다.

 

눈여겨 봐야할건 환율계산하기 버튼이 없다는 점 입니다.

 

View에 데이터를 입력하는순간 데이터바인딩으로 연결된 ViewModel에 데이터가 넘어가 로직이 진행되게 됩니다.

 

2. 프로젝트 셋팅하기

 

(1) 디렉토리 및 파일 구성하기

wpf프로젝트가 열리면 MainWindow.xaml을 과감히 지워버리시고 

 

솔루션파일에 Model, View, ViewModel 디렉토리를 생성한후 아래와같이 class, window, class를 만들어줍니다.

 

 

(2)App.xaml 수정하기

<Application x:Class="ExchangeCalculator.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:ExchangeCalculator"
             StartupUri="View/MainWindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

 

StartupUri는 앱의 시작지점으로 기본으로 "MainWindow.xaml"이 지정되어있습니다.

 

그러나 우리는 View라는 디렉토리 안에 MainWindow를 만들어 놨으므로 View/MainWindow.xaml로 변경해줍니다.

 

(안드로이드의 manifest파일과 유사합니다.)

3. Model/MainModel.cs

namespace ExchangeCalculator.Model
{
    public class MainModel
    {
        private string dollar;
        private string won;
    }
}

ViewModel과 주고받을 데이터를 멤버변수로 정의합니다.

4. View/MainWindow.cs

namespace ExchangeCalculator.View
{
    /// <summary>
    /// MainWindow.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

 

그동안 봐왔던 MainWindow.cs의 역할은 ViewModel에서 처리 하므로 비워둡니다.

5. View/MainWindow.xaml

<Window x:Class="ExchangeCalculator.View.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:ExchangeCalculator.View"
        xmlns:viewModel="clr-namespace:ExchangeCalculator.ViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <viewModel:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"></ColumnDefinition>
            <ColumnDefinition Width="1*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="1*"></RowDefinition>
            <RowDefinition Height="1*"></RowDefinition>
            <RowDefinition Height="1*"></RowDefinition>
        </Grid.RowDefinitions>

        <Grid Grid.Row="0" Grid.ColumnSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center">
            <TextBlock Text="Dollar to Won" FontSize="50"></TextBlock>
        </Grid>

        <Grid Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock Text="dollar" FontSize="20"></TextBlock>
        </Grid>

        <Grid Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBox FontSize="20" Width="150" Text="{Binding Path=Dollar, UpdateSourceTrigger=PropertyChanged}" TextAlignment="Center"></TextBox>
        </Grid>

        <Grid Grid.Column="0" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock Text="won" FontSize="20"></TextBlock>
        </Grid>

        <Grid Grid.Column="1" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBox FontSize="20" Width="150" Text="{Binding Path=Won}" IsReadOnly="True" TextAlignment="Center"></TextBox>
        </Grid>
    </Grid>
</Window>

 

새로운 디렉토리 안에 클래스파일을 추가 했으므로 네임스페이스를 사용한다고 명시해줘야합니다.

 

xmlns:viewModel="clr-namespace:ExchangeCalculator.ViewModel"

윈도우 태그안에 해당 코드를 넣어줍니다.

 

MVVM 패턴은 코드 비하인드를 MainWindow.cs 로 하지 않습니다.

 

MainViewModel이 View단을 책임지는 ViewModel이므로 아래 해당코드를 추가해주시면 됩니다.

<Window.DataContext> 
    <viewModel:MainViewModel/> 
</Window.DataContext>

달러를 입력하는 TextBox.Text의 Binding Path와 원을 보여주는 TextBox.Text의 Binding Path는

 

ViewModel에서 바인딩할 Dollor와 Won을 각각 넣어주고

 

달러는 View의 변경을 ViewModel에서 즉각적으로 반영할 수 있도록 UpdateSourcTrigger를 PropertyCanged로 설정해줍니다.

 

원은 입력하지 못하도록 IsReadOnly를 True로 설정해줍니다.

6. ViewModel/MainViewModel.cs

namespace ExchangeCalculator.ViewModel
{
    class MainViewModel : INotifyPropertyChanged
    {
        private MainModel myModel = null;

        public MainViewModel()
        {
            myModel = new MainModel();
        }

        public string Dollar
        {
            get
            {
                if(string.IsNullOrEmpty(myModel.dollar))
                {
                    Won = "0";
                }
                else
                {
                    int num = -1;
                    if (int.TryParse(myModel.Dollar, out num))
                    {
                        int result = num * 1160;
                        Won = result.ToString();
                    }
                    else
                    {
                        MessageBox.Show("Please insert number","Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        Dollar = "";
                        Won = "0";
                    }
                }
                return myModel.dollar;
            }
            set
            {
                if (myModel.dollar != value)
                {
                    myModel.dollar = value;
                    OnPropertyChanged("Dollar");
                }
            }
        }

        public string Won
        {
            get
            {
                return myModel.won;
            }
            set
            {
                myModel.won = value;
                OnPropertyChanged("Won");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string prop)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(prop));
            }
        }
    }
}

myModel 객체를 생성해주고

 

View단과 바인딩할 Won, Dollar를 속성변경 이벤트 처리해줍니다.

 

Dollor가 변경자마자 PropertyChanged 처리 된 뷰단에서 바로 데이터를 가져가 게터가 호출되므로

 

게터에서 현재환율(2020.10.02기준)인 1160을 곱해 Won의 값을 변경해줍니다.(또 Won의 세터가 호출되고 속성변경 이벤트가 호출되어 View가 바로 변경됩니다.)

 

(PropertyChanged예제 링크 남깁니다.)

 

frozenpond.tistory.com/55?category=1126752

 

[wpf] ListView 사용법 및 예제 -3-(INotifyPropertyChanged.PropertyChanged 사용하기)

ListView 사용법 및 예제는 총 4개의 게시글로 구성되어있습니다. ListView 사용법 및 예제 -1- ListView 사용법 및 예제 -2-(ObservableCollection 사용하기) ListView 사용법 및 예제 -3-(INotifyPropertyChange..

frozenpond.tistory.com

 

 

 

 

반응형

댓글