WPF : MVVM(Model - View - ViewModel)

2026. 4. 23. 11:49·FRAMEWORK/WPF

1. MVVM 

[View (XAML)]
   ↓ Binding
[ViewModel]
   ↓ 데이터 처리
[Model]

2. Model(Data)

  • 데이터
  • UI 를 알 필요없음
  • 로직 X
public class Car
{
    public string Name { get; set; }
    public int Speed { get; set; }
}

3. ViewModel

 1) 역할

  • UI에 보여줄 데이터 관리(Model > ViewModel > View)
  • UI 이벤트 처리(View > ViewModel > Model)
  • 상태 변경

 2) 핵심 기능

  • Property(데이터 처리)
  • Command(명령)
using System.ComponentModel;
using System.Windows.Input;

public class MainViewModel : INotifyPropertyChanged
{
    private Car _car;

    public MainViewModel()
    {
        _car = new Car
        {
            Name = "Tesla",
            Speed = 0
        };

        StartCommand = new RelayCommand(Start);
        StopCommand = new RelayCommand(Stop);
    }

    // 바인딩 속성
    public string CarName
    {
        get => _car.Name;
        set
        {
            _car.Name = value;
            OnPropertyChanged(nameof(CarName));
        }
    }

    public int Speed
    {
        get => _car.Speed;
        set
        {
            _car.Speed = value;
            OnPropertyChanged(nameof(Speed));
        }
    }

    // Command (명령)
    public ICommand StartCommand { get; }
    public ICommand StopCommand { get; }

    private void Start()
    {
        Speed = 100;
    }

    private void Stop()
    {
        Speed = 0;
    }

    // Binding 필수 구현
    public event PropertyChangedEventHandler PropertyChanged;

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

3.1 PropertyChangedEventHandler(Property 구현)

더보기

※ 위 ViewModel 참고

1) 바인딩 속성에 있어 Property 형식이 필요한 이유

public string CarName
{
    get => _car.Name;
    set
    {
        _car.Name = value;
        OnPropertyChanged(nameof(CarName));
    }
}
  • 이유) string 데이터를 일반 변수가 아닌 Property로 구현 : 바인딩한 View에게 알림을 주기 위해서임.
  • 예를 들어) public string CarName이 일반변수인 경우 CarName의 값이 변경되어도 View는 알 방법이 없음.
  • 따라서) 값이 변경되는 경우(Property : set) → OnPropertyChanged() 를 호출함으로써 View에게 알림을 주는 것.

2) PropertyChangedHandler 객체

public event PropertyChangedEventHandler PropertyChanged;
  • PropertyChangedEventHandler 객체인 PropertyChanged 를 생성한다.

3) OnPropertyChanged() 메서드

protected void OnPropertyChanged(string name)
{
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
  • 위 바인딩 속성의 set 에서 호출하는 메서드를 구현한다.

3.2 RelayCommand(Command 구현)

더보기

1) RelayCommand 가 필요한 이유

  • MVVM 내부 구조는 아래처럼 진행됨
[사용자 컨트롤 사용]
        ↓
[컨트롤]
        ↓
Command.Execute() 호출 (내부적)
        ↓
RelayCommand.Execute()
        ↓
Start() 와 같은 바인딩 메서드 실행

 

2) ViewModel 에서 사용되는 구조

public ICommand StartCommand { get; }
public ICommand StopCommand { get; }

private void Start()
{
    Speed = 100;
}

private void Stop()
{
    Speed = 0;
}

> ICommand 형 Command 생성

 

public MainViewModel()
{
    _car = new Car
    {
        Name = "Tesla",
        Speed = 0
    };

    StartCommand = new RelayCommand(Start);
    StopCommand = new RelayCommand(Stop);
}

> 해당 객체를 RelayCommand 형으로 동적 생성

> RelayCommand 는 ICommand 를 상속하는 구조로써 객체지향 프로그래밍 특징 중 하나인 다형성을 활용해 기반 클래스 객체이더라도 파생클래스 형태로 동적으로 생성할 수 있다.

 

3) RelayCommand 구현

using System;
using System.Windows.Input;

public class RelayCommand : ICommand
{
    private readonly Action _execute;

    public RelayCommand(Action execute)
    {
        _execute = execute;
    }

    public bool CanExecute(object parameter) => true;

    public void Execute(object parameter)
    {
        _execute();
    }

    public event EventHandler CanExecuteChanged;
}

 

3.1) Excute() 호출 구조 : MainViewModel의 Startcommand 기준

1. RelayCommand 형 객체 동적 생성

StartCommand = new RelayCommand(Start);

2. RelayCommand 의 생성자에 의해 _excute == Start() 가 됨

3. 사용자의 Control 사용

4. Control 은 Command.Excute() 호출(WPF 내부적 호출)

5. 바인딩된 RelayCommand.Excute() 호출

6. _excute() 호출 == Start() 호출

 

3.2) CanExcute() 호출 구조

1. 내부적으로 Control은 아래처럼 작동

if (Command.CanExecute(null))
{
    버튼 활성화
}
else
{
    버튼 비활성화
}

2. Control 활성화

public bool CanExecute(object parameter) => true;

> 항상 CanExcute 가 true 를 반환하도록 구현하였으므로, 언제나 Control은 활성화되어 있다.


4. View(XAML)

<Window x:Class="MVVMTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <StackPanel Margin="20">

        <TextBlock Text="Car Name"/>
        <TextBox Text="{Binding CarName, Mode=TwoWay}" />

        <TextBlock Text="Speed"/>
        <TextBlock Text="{Binding Speed}" FontSize="20"/>

        <Button Content="Start"
                Command="{Binding StartCommand}"
                Margin="0,10,0,0"/>

        <Button Content="Stop"
                Command="{Binding StopCommand}"/>

    </StackPanel>
</Window>

 

1) UI 표시(데이터 바인딩)

<TextBlock Text="Car Name"/>
<TextBox Text="{Binding CarName, Mode=TwoWay}" />

<TextBlock Text="Speed"/>
<TextBlock Text="{Binding Speed}" FontSize="20"/>

> Property Data 를 Text 에 Binding 하여 사용함

 

2) Contrl(명령 바인딩)

<Button Content="Start"
        Command="{Binding StartCommand}"
        Margin="0,10,0,0"/>

<Button Content="Stop"
        Command="{Binding StopCommand}"/>

> Command 를 Control(Button) 에 Binding 하여 사용함

 

4.1 ViewModel - View 연결

public MainWindow()
{
    InitializeComponent();
    DataContext = new MainViewModel();
}
DataContext = new MainViewModel();

> 해당 내용은 View 는 MainViewModel 을 기준으로 사용한다 라는 의미임.

'FRAMEWORK > WPF' 카테고리의 다른 글

WPF : ViewModel - DI(의존성 주입)  (0) 2026.04.25
WPF : Model  (0) 2026.04.25
WPF : 타이머 만들기  (0) 2026.04.23
WPF : WPF 에 대하여  (0) 2026.04.22
'FRAMEWORK/WPF' 카테고리의 다른 글
  • WPF : ViewModel - DI(의존성 주입)
  • WPF : Model
  • WPF : 타이머 만들기
  • WPF : WPF 에 대하여
m_Dev
m_Dev
  • m_Dev
    m_Dev
    m_Dev
  • 전체
    오늘
    어제
    • 분류 전체보기
      • MAIN STUDY
        • 정보보안
        • 빅데이터
        • 정보처리
        • 컴퓨터 구조
        • 기타
      • JOB
        • Study
        • Project
      • LMS 7
        • 개발일지
      • FRAMEWORK
        • Qt
        • MFC
        • Winform
        • WPF
        • MAUI
      • NETWORK
        • Study
        • Assignment
      • PYTHON
        • Set
        • Study
        • Assignment
        • Project
      • C
        • Set
        • Study
        • Assignment
        • Project
      • C++
        • Set
        • Study
        • Assignment
        • Project
      • C#
        • Set
        • Study
        • Assignment
        • Project
      • DATABASE
        • MySQL
        • SQLite
      • IDE
        • VisualStudioCode
        • VisualStudio
        • Pycharm
        • Colab
      • 기타
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
m_Dev
WPF : MVVM(Model - View - ViewModel)
상단으로

티스토리툴바