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

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

 

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

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

 

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

 

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

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

 

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  옵션은 사용하지 않아 제거했습니다.

 

3. 폴더 생성 및 MainWindowViewModel 만들기

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

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

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 파일을 하나 생성합니다.

 

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해주는 방식으로 추가해가면 됩니다.