[WPF/CommunityToolkit.Mvvm] 1. 프로젝트 생성 후 boilerplate 코드 작성하기

※. Visual Studio 2022 기준 스크린 샷입니다.

 

1. Visual Studio를 열고 새로운 WPF 프로젝트를 하나 생성합니다.

WPF로 검색해서 WPF Application 프로젝트 템플릿을 찾아서 선택합니다.

etc-image-0

 

프로젝트 생성 경로와 솔루션 이름 프로젝트명을 지정합니다.

etc-image-1

 

여기서는 .Net 6.0 이상을 기준으로 설명하므로 6.0을 선택합니다.

etc-image-2

프로젝트 생성이 완료되면 Solution Explorer에 아래와같이 생성된 솔루션과 프로젝트 내의 파일을 확인합니다.

etc-image-3

 

2. NuGet Package 설치하기

NuGet Package Manager에서 아래 패키지들을 설치하거나 Solution Explorer에서 프로젝트(MyTestApp)를 double-click해서 프로젝트 파일을 열어 아래의 PackageReference 태그를 바로 추가하고 저장합니다.

  <ItemGroup>
	<PackageReference Include="CommunityToolkit.Mvvm" Version="8.1.0" />
	<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
  </ItemGroup>

※. 저는 취향상 Nullable  옵션은 사용하지 않아 제거했습니다.

etc-image-4

 

3. 폴더 생성 및 MainWindowViewModel 만들기

프로젝트 내에 Views, ViewModels 두 개의 폴더를 생성한 다음 MainWindow.xaml 파일을 Views 폴더로 옮겨줍니다. 폴더명은 개인 취향이므로 본인이 원하는 폴더명으로 지정해도 무관합니다.

etc-image-5

MainWindow.xaml 파일을 Views 폴더 안으로 옮겼기 때문에 App.xaml에 StartupUri를 아래와 같이 수정합니다.

etc-image-6

ViewModels 폴더 안에 새로운 class 파일 MainWindowViewModel.cs 을 생성합니다.

 

MVVM 툴깃의 코드 생성 기능을 사용하기 위해서 partial 키워드를 추가하고 아래와같이 ObservableObject를 상속받는 class로 정의합니다.

using CommunityToolkit.Mvvm.ComponentModel;

namespace MyTestApp.ViewModels
{
    public partial class MainWindowViewModel : ObservableObject
    {
    }
}

C#은 다중상속이 지원되지 않기 때문에 ViewModel이 특정 class를 상속 받아야하는 경우라면 ObservableObject를 상속받는 대신 아래와같이 INotifyPropertyChanged Attribute를 선언해주면 됩니다.

using CommunityToolkit.Mvvm.ComponentModel;

namespace MyTestApp.ViewModels
{
    public class MyBaseClass
    {
    }

    [INotifyPropertyChanged]
    public partial class MainWindowViewModel : MyBaseClass
    {
        public MainWindowViewModel()
        {
        }
    }
}

 

4. ViewModel Locator 클래스 생성하기

프로젝트에 VmLocator.cs 파일을 하나 생성합니다.

etc-image-7

 

ViewModel에서 Dependency Injection을 사용하기 위해 이 파일에서 아래와같이 dependency들을 정의합니다.

using Microsoft.Extensions.DependencyInjection;
using MyTestApp.ViewModels;
using System;

namespace MyTestApp
{
    public class VmLocator
    {
        public IServiceProvider Services { get; }

        public VmLocator()
        {
            var services = new ServiceCollection();

            services.AddTransient<MainWindowViewModel>();

            Services = services.BuildServiceProvider();
        }

        public MainWindowViewModel MainWindowVM => Services.GetService<MainWindowViewModel>();
    }
}

 

이제 앱이 실행 될 때 VmLocator의 Instance가 생성되도록 App.xaml에 아래와같이 tag를 추가해줍니다.

<Application x:Class="MyTestApp.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:MyTestApp"
             StartupUri="Views/MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <local:VmLocator x:Key="VmLocator" />
        </ResourceDictionary>
    </Application.Resources>
</Application>

 

5. View에 ViewModel 바인딩 하기

MainWindow.xaml 파일에 DataContext를 아래와같이 MainWindowVM에 바인딩 해줍니다.

<Window x:Class="MyTestApp.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:MyTestApp"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        DataContext="{Binding Source={StaticResource VmLocator}, Path=MainWindowVM}">
    <Grid>

    </Grid>
</Window>

 

 여기까지가 MVVM 패턴으로 WPF 앱을 개발하기 위한 Boilerplate 코드입니다. 새로운 View는 Views 폴더에 추가하고 해당 View에 대한 ViewModel은 ViewModels에 폴더에 추가 후 해당 ViewModel의 Instance가 Dependancy Inject 서비스에의해 생성되도록 MainWindowVM과 같은 방법으로 VmLocator에 선언한 뒤 View의 DataContext에 Binding해주는 방식으로 추가해가면 됩니다.