티스토리 뷰
2022.09.06 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내v1.0 part9-2 StyleSelector
2022.08.31 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 v1.0 part9-1 DataTemplateSelector
2022.08.08 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 v1.0 part8-3 Template
2022.08.02 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 v1.0 part8-2 Template
2022.07.21 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 v1.0 part8-1 Template
2022.07.13 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 v1.0 part7 Behavior
2022.07.05 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 V1.0 part6 Command
2022.06.27 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 V1.0 part5 Converter
2022.06.15 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 V1.0 part4-2 Data Binding
2022.06.13 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 V1.0 part4-1 Data Binding
2022.06.07 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 V1.0 part3-3
2022.06.02 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 V1.0 part3-2
2022.05.30 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 V1.0 part3-1
2022.05.11 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 v1.0 part2
2022.05.09 - [WPF .NET] - MVVM Pattern을 사용하는 개발자를 위한 안내 v1.0 part1
이번 파트에서는 MVVM Pattern을 실제 프로젝트에서 구현하는 방법에 대해서 알아보도록 하겠습니다.
1. INotifyPropertyChanged
- 프로퍼티가 변경되었음을 클라이언트에게 알려주는 핵심 인터페이스 입니다.
- Platform의 controls들은 이 이벤트를 수신해서 처리합니다.
구현 예)
- 프로젝트에서 INotifyPropertyChanged 인터페이스를 사용하기 위해서는 아래와 같은 base 클래스를 만들어서 Model이나 ViewModel에서 상속 받아 사용하면 됩니다.
- [CallerMemberName] 때문에, Visual Studio 2017 이상에서 동작할 것으로 보입니다.
public class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
{
if (Equals(storage, value))
{
return;
}
storage = value;
OnPropertyChanged(propertyName);
}
protected void OnPropertyChanged(string propertyName)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
2. ICommand
- UI에서 사용자의 입력을 ViewModel에 전달합니다.
- Button control은 Command 프로퍼티가 있지만, 다른 컨트롤에서 Command를 이용하기 위해서는 Behavior nuget이 필요합니다.
구현 예)
주로 DelegateCommand 혹은 RelayCommand로 만들어서 사용합니다.
아래 구현예는 CommandParameter를 수신할 수 없는 형태입니다.
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public event EventHandler CanExecuteChanged;
public RelayCommand(Action execute)
: this(execute, null)
{
}
public RelayCommand(Action execute, Func<bool> canExecute)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
public void OnCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}
1, 2번이 가장 핵심 개념으로 이 두가지만 사용해도 간단한 프로그램을 만드는 것은 문제가 없습니다. 하지만, 프로젝트가 약간만 커져도 금방 한계를 만나게 됩니다.
3. 향상된 MVVM Pattern 사용
- 관심사의 분리(Separation of concerns)를 위해서...
- Dependency Inversion Principle(종속성 반전 원칙 - DIP로 표현합니다)
- 시스템의 High level 부분과 Low level 부분을 인터페이스를 사용하여 분리하는 원칙입니다. 이를 구현하기 위해서는 아래 두가지가 필요합니다. 더 자세한 사항은 여기를 참고하시기 바랍니다.
- Dependency Injection(의존성 주입 - DI) : 뷰모델에서 사용할 객체(서비스)를 Container를 이용해서 만들거나 가져와서 강제로 주입을 하는 것을 이야기합니다.
- IoC Container(Inversion of Control Container) : Dependency Injection을 수행하기 위해 필요한 의존성이 없는 공용 저장소를 이야기합니다.
- 시스템의 High level 부분과 Low level 부분을 인터페이스를 사용하여 분리하는 원칙입니다. 이를 구현하기 위해서는 아래 두가지가 필요합니다. 더 자세한 사항은 여기를 참고하시기 바랍니다.
- Dependency Inversion Principle(종속성 반전 원칙 - DIP로 표현합니다)
- Communication
- ViewModel과 ViewModel은 의존성을 가지지 않기 때문에 소통을 위한 기능이 필요합니다.
- 예) Messenger(Microsoft Toolkit.Mvvm), EventAggregator(Prism framework)
4. MVVM Pattern NuGet packages
- 프로젝트를 개발할 때는 사용하는 NuGet packages 입니다.
- MVVMLight – 2.65M
- DevExpressMvvm – 119K
- MvvmCross – 4.65M
- Microsoft.Toolkit.Mvvm – 296K
- Prism Library – (Prism.Core 10M)
1~3번까지의 기능들을 모두 나혼자 구현해야한다면, 아마 프로젝트를 시작하기전부터 지쳐서 의욕 상실할 것입니다. 요즘 대세는 빠르게 배우고 빠르게 만드는 언어가 인기인데 말이죠.. 그래서, 많은 개발자들은 NuGet에서 자신이 원하는 라이브러리를 다운받아서 사용합니다.
5. MVVMLight – 2.65M
- GalaSoft에서 제공한 MVVM Tool로 작고 가볍게 사용할수 있어서 많은 개발자들이 사용했습니다.
- CommonServiceLocator, MvvmLight, MvvmLightLibs
- .Net Framework, PCL 지원
- Visual Studio 지원 : 2012 ~ 2017
- Platform 지원 : Xamarin.Android, Xamarin.iOS, Xamarin.Forms, Windows 10 UWP, WPF, Silverlight, Windows Phone
- 장점 : MVVM 패턴 사용을 위한 기본적인 구성요소를 대부분 가지고 있으며, 가볍게 사용할 수 있습니다.
- 단점 : 몇년전 개발 중단으로 Visual Studio 2019 이상을 지원하지 않고, Document 링크도 깨져서 사용이 어렵습니다.
6. DevExpressMvvm – 119K
- DevExpress사가 제공하는 MVVM 프레임워크입니다.
- DevExpress.Mvvm
- Visual Studio 지원 : 2012 ~ 2022
- Platform 지원 : WPF
- 장점 : DevExpress 라이브러리와 같이 설치됨, DevExpress사에서 관리하는 소스로 안정성 높음(보안)
- 단점 : ? (프로젝트를 진행 보지 못해 모르겠습니다. nuget에서 다운로드 받아서 사용할 수 있다는 제보가 있었습니다. )
7. MvvmCross – 4.65M
- 오픈 소스 기반 라이브러리입니다.
- MvvmCross, MvvmCross.Forms, MvvmCross.Tests 등 다수의 nuget package
- Visual Studio 지원 : 2019 ~ (별도 표시가 없음)
- Platform 지원 : Xamarin.iOS, Xamarin.Android, Mamarin.Mac, Xamarin.Forms, UWP, WPF
- 장점 : Cross-platform에 최적화되어 있는 라이브러리
- 단점 : 다른 라이브러리와 달리 MvvmCross만의 바인딩 방식과 커맨드 처리 방식이 있어서 별도 학습 필요, 여러 종류의 nuget이 있어서 설정하는것이 쉽지 않음
8. Microsoft.Toolkit.Mvvm – 296K .NET 5, .NET Standard 2.0
CommunityToolkit.Mvvm 으로 변경되었습니다. .NET 6, .NET Standard 2.0
.NET 5는 지원 기간이 끝났습니다.
- Microsoft에서 관리하는 MVVM Tool로, 쉽고 간단하게 MVVM을 적용할 수 있습니다.
- Microsoft.Toolkit.Mvvm, Microsoft.Extensions.DependencyInjection
- .NET Standard 2.0, 2.1, .NET 5
- Visual Studio 지원 : 2017~2022
- Platform 지원 : Xamarin.Android, Xamarin.iOS, Xamarin.Forms, Windows 10 UWP, WPF, Windows App SDK
- 장점 : 플랫폼 및 런타임에 독립적(.NET Standard 2.0 and .NET 5), 유연한 구조로 사용이 간편, MVVMLight 개발진 참여
- 단점 : 기본 기능들만 존재하며, 대규모 프로젝트에서 사용할 수 있는 기능 미흡
9. Prism Library – (Prism.Core 10M)
- Microsoft에서 관리하다 Open Source 프로젝트로 전환된 라이브러리로, 안정성과 대규모 프로젝트 개발에 적합합니다.
- Prism.Core, Prism.Wpf, Prism.Forms 등 다수의 nuget package
- Visual Studio 지원 : 2017 ~ 2022
- Platform 지원 : Xamarin.Forms, WPF, UWP, Uno Platform
- 장점 : 안정성과 성능이 우수하고, 대규모 프로젝트에서 사용할 수 있는 기능 포함
- 단점 : 대규모 프로젝트에 필요한 기능을 추가 학습하는 시간이 필요하고, 환경설정 및 Framework 개발에 난이도가 있음
10. 라이브러리별 비교
MVVMLight | DevExpressMvvm | MvvmCross | MVVM Toolkit | Prism Library | |
INotifyPropertyChanged | ObservableObject | BindableBase | MvxNotifyPropertyChanged | ObservableObject | BindableBase |
ICommand | RelayCommand | DelegateCommand, AsyncCommand | MvxCommand MvxAsyncCommand |
RelayCommand AsyncRelayCommand |
DelegateCommand |
IoC | SimpleIoc | Autofac | Mvx.IoCProvider | Microsoft.Extensions.DependencyInjection | Prism.Unity, Prism.DryIoc |
Message Communication |
Messenger | DevExpress.Mvvm.Messenger | IMvxMessenger | WeakReferenceMessenger, StrongReferenceMessenger | EventAggregator |
Module dev support | X | Module Injection Framework | ? | X | IModule |
Dialog show/hide | X | ? | IMvxInteraction | X | IDialogService |
Use split screen/control | X | ? | ? | X | IRegionManager |
Template | X | O | O | X | O |
Open Source | O | X | O | O | O |
저는 간단한 프로젝트는 Microsoft.Toolkit.Mvvm을 사용하고, 시스템 개발 프로젝트에서는 Prism library를 이용해서 개발을 진행 합니다.
MvvmCross는 저도 사용해 본적이 없어서 뭐라고 이야기를 못할것 같고, MVVMLight는 이제 사용하시면 않됩니다.
DevExpressMvvm은 Open source를 사용하지 못하는 프로젝트에서 사용하시면 좋을 것 같습니다.
MVVM Pattern을 구현하는 방법에 대해서 알아 보았고, 다음 포스트는 이벤트 드리븐 프로그래밍과 MVVM Pattern의 차이점에 대해서 살펴 보도록 하겠습니다.
'WPF .NET' 카테고리의 다른 글
Dependency Inversion Principle(DIP) - 의존성 역전 원칙 part2 (6) | 2022.05.20 |
---|---|
Dependency Inversion Principle(DIP) - 의존성 역전 원칙 part1 (2) | 2022.05.19 |
MVVM Pattern을 사용하는 개발자를 위한 안내 v1.0 part1 (15) | 2022.05.09 |
Microsoft.Toolkit.Mvvm을 이용한 간단한 프레임워크 part6 - 유효성 검사 추가 (2) | 2022.04.21 |
Syncfusion Metro Studio 5으로 아이콘 쉽게 만들어서 사용하기 (0) | 2022.04.18 |
- Total
- Today
- Yesterday
- #uwp
- Always Encrypted
- UWP
- #prism
- Bot Framework
- Windows 10
- #MVVM
- WPF
- ComboBox
- PRISM
- dotNETconf
- Microsoft
- kiosk
- Cross-platform
- IOT
- uno-platform
- Build 2016
- XAML
- uno platform
- MVVM
- C#
- windows 11
- LINQ
- #Windows Template Studio
- .net 5.0
- Behavior
- Visual Studio 2022
- ef core
- visual studio 2019
- .net
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |