본문 바로가기
Study/WPF

[WPF][MVVM][Study] MVVM 실습 2 - 단위 변환기 2

by 스테디코디스트 2023. 9. 21.
반응형
이번에는 버튼을 눌러야만 단위를 변환해주는 단위 변환기를 만드는 실습을 해보았다.

1 ~ 3. (실습 1)을 참고하여 기본적인 작업을 참고

 

4. Command 클래스 생성 및 코드 작성

1) Command 클래스를 생성한다.(프로젝트>추가>클래스)

2) 인터페이스 ICommand를 상속받아서 인터페이스를 구현해준다.

3) 생성자를 이용해 외부의 실행 전 조건을 검사할 함수와 실제로 실행할 함수를 저장한다. 

// Command.cs
using System;
using System.Windows.Input;

namespace WPF_MVVM_EX_2
{
    class Command : ICommand
    {
        Action<object> ExecuteMethod;
        Func<object, bool> CanexecutedMethod;

        public Command(Action<object> execute_Method, Func<object, bool> canexecuted_Method)
        {
            this.ExecuteMethod = execute_Method; // Action으로 버튼에 바인딩된 커맨드가 실제로 실행할 함수
            this.CanexecutedMethod = canexecuted_Method; // Action 수행 전 필요 조건을 검사
        }

        public event EventHandler CanExecuteChanged;

        // 실행 전 조건을 검사하는 메소드
        public bool CanExecute(object parameter)
        {
            return true;
        }

        // 실제로 실행할 메소드
        public void Execute(object parameter)
        {
            ExecuteMethod(parameter);
        }
    }
}

 

5. Model 코드 작성

1) 변수 kg과 lb를 생성 (get,set 프로퍼티 이용)

2) 변수들의 값이 변할 때 UI를 업데이트 시켜주는 인터페이스 INotifyPropertyChanged를 상속받아 구현

3) lb에 의해서 kg의 값이 생성될 때(변환 버튼을 누른 경우) 인터페이스 함수 동작

// MainModel.cs
using System.ComponentModel;

namespace WPF_MVVM_EX_2.Model
{
    class MainModel : INotifyPropertyChanged
    {
        private float kg = 0;
        public float Kg
        {
            get => kg;
            set
            {
                kg = value;
                OnPropertyChanged("Kg"); // UI 업데이트
            }
        }

        private float lb = 0;

        public float Lb
        {
            get => lb;
            set
            {
                lb = value;                 
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string name)
        {
			// name에 해당되는 프로퍼티가 변경될 경우 동작
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}

 

6. ViewModel 코드 작성

1) Model, Command 변수 선언

2) MainModel과 마찬가지의 이유로 INotifyPropertyChanged 인터페이스 구현

3) Command로 넘겨 줄 함수 구현(Excute_fuc, CanExecute_fuc)

4) 버튼을 눌렀을 때 실행되는 함수인 Excute_fuc에 lb->kg 변환 공식 이용(lb/2.2 ->kg)

// MainViewModel.cs
using System.ComponentModel;

namespace WPF_MVVM_EX_2.ViewModel
{
    class MainViewModel : INotifyPropertyChanged
    {
        public Command btn_cmd { get; set; }
        private Model.MainModel model = null;
        
        public Model.MainModel Model
        {
            get => model;
            set
            {
                model = value;
                OnPropertyChanged("Model"); // UI 업데이트
            }
        }

        public MainViewModel()
        {
            model = new Model.MainModel();
            btn_cmd = new Command(Execute_fuc, CanExecute_fuc);
        }
        
        // 버튼 누를 시 실행되는 함수
        private void Execute_fuc(object obj)
        {
            model.Kg = (float)((int)((model.Lb / 2.2f) * 100)) / 100; // 소수점 둘째자리까지만 구함
        }

		// 버튼을 누른 이후, Execute_fuc이 실행되기 전 조건을 검사하는 함수
        private bool CanExecute_fuc(object obj)
        {
            return true;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}

 

7. XAML 바인딩

1) lb와 kg를 나타낼 각 TextBox의 Text 속성에 Model의 각 변수들을 바인딩

2) Button에 Command를 바인딩

<!--MainWindow.xaml-->
<Window
        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:WPF_MVVM_EX_2"
        xmlns:ViewModel="clr-namespace:WPF_MVVM_EX_2.ViewModel" x:Class="WPF_MVVM_EX_2.MainWindow"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <ViewModel:MainViewModel/>
    </Window.DataContext>
    <Grid Margin="50,30,50,50" Width="420" Height="220">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        
        <Label Content="단위 변환 2" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center" Grid.ColumnSpan="2" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Height="26" Width="74"/>
        <Label Content="lb" HorizontalAlignment="Center" Margin="0,0,0,10" VerticalAlignment="Bottom" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"/>
        <Label Content="kg" HorizontalAlignment="Center" Margin="0,0,0,10" VerticalAlignment="Bottom" Grid.Column="1" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"/>
        <TextBox HorizontalAlignment="Center" Height="23" Margin="0" TextWrapping="Wrap" Text="{Binding Model.Lb}" VerticalAlignment="Top" Width="120" TextAlignment="Center" Grid.Row="1" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
        <TextBox HorizontalAlignment="Center" Height="23" Margin="0" TextWrapping="Wrap" Text="{Binding Model.Kg}" VerticalAlignment="Top" Width="120" TextAlignment="Center" Grid.Column="1" Grid.Row="1" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
        <Button Content="변환" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center" Width="75" Grid.Row="1" Grid.ColumnSpan="2" Panel.ZIndex="-3" Command="{Binding btn_cmd}"/>

    </Grid>
</Window>

 

8. 결과

- 파운드를 입력했을 때 kg으로 잘 변환이 되는 것을 볼 수 있다!

 

9. MVVM 구조에 따른 동작원리

1) View의 lb란에 숫자를 입력 후 변환 버튼 누름

2) View와 연결된 ViewModel에서 Model 인스턴스 생성 및 버튼 동작에 따른 Command 함수 동작

3) ViewModel에서는 Model과 연결된 변수에 접근하여 변환 함수 실행

4) Model에서 set 프로퍼티의 OnPerpertyChanged 함수에 의해 kg으로 변환된 숫자가 ViewModel의 Model 인스턴스에 전달되어 해당 set 프로퍼티의 OnPerpertyChanged 함수가 동작하게 되고, 그로인해 View에 변환된 kg이 나오게 된다.

 

 

cf) 참고 자료

https://esound.tistory.com/12

 

[C# WPF] MVVM 간단하게 시작하기 - 2 (버튼, 버튼커맨드)

오늘은 MVVM에서 버튼을 클릭했을 때, 함수를 실행시킬 수 있는 커맨드를 작성해보겠습니다. 이전의 글에서는 데이터 바인딩을 통해 숫자가 입력되면 자동으로 입력된 숫자에 2가 곱해져 출력되

esound.tistory.com