아메리카노
1
SW 아키텍처를 전반적으로 설계하는 도중 궁금증이 들어 질문드립니다.
MVVM 구조로 프로그램을 설계하면 View와 ViewModel을 매핑해야합니다.
방법마다 장단점이 있는걸 알지만 다들 어떻게 하시는지 궁금합니다.
- DataTemplate 방식
<DataTemplate DataType="{x:Type vm:MainViewModel}"> <view:MainViewModel/> </DataTemplate>
- ViewModelLocator 패턴
<!-- App.xaml -->
<Application.Resources>
<vm:ViewModelLocator x:Key="Locator" />
</Application.Resources>
<!-- LoginView.xaml -->
<UserControl DataContext="{Binding LoginViewModel, Source={StaticResource Locator}}">
<!-- View content -->
</UserControl>
- 코드 비하인드에서 DI 주입
public LoginView()
{
InitializeComponent();
// 예: DI 컨테이너로부터 ViewModel 주입
DataContext = Bootstrapper.ServiceProvider.GetService<LoginViewModel>();
}
이외에도 여러 방법이 있지만 프로덕트로 설계할 때는 어떤 방법을 사용하는게 좋은지 헷갈립니다.
1 Like
leechw9
2
DataContext Tunneling 을 활용하는 것이 좋다고 생각합니다.
1 Like
아메리카노
3
자식 ViewModel이 부모 ViewModel의 무언가를 사용할 수 있는 방식이 맞나요?
이 경우 자식이 부모에게 종속되어 mvvm에 위배된다는 생각이 들어서 여쭙습니다.
제품 특성에 따라서 어느정도 용인해야할까요?
leechw9
4
종속 없다면,
DataContext = new ViewModel();
이렇게 하겠습니다.
1 Like
우선, 설정 우선 순위는 코드 비하인드에서의 설정이 우선합니다.
public LoginView()
{
// XAML 요소의 DataContext attribute로부터 DataContext 속성 설정됨.
InitializeComponent();
// 재설정 => 최종적인 설정.
DataContext = Bootstrapper.ServiceProvider.GetService<LoginViewModel>();
// DataContext = new LoginViewModel();
}
Static Resource
말 그대로, static 합니다.
뷰가 앱의 생애 주기 동안 고정 표시된다면 뷰모델이 static 해도 상관이 없지만, 그렇지 않다면, 메모리에 깔아 둘 이유는 없을 것 같습니다.
뷰모델 객체는 해당 뷰가 없어질 때 함께 없어지는 편이 메모리 측면에서 유리할 것입니다.
식별자 위치
XAML 은 약간의 한계를 가지고 있는데, 스크립트에 식별자만 넣을 수 있을 뿐, 아래와 같이 expression 을 넣을 수 없다는 점입니다.
<Button Clicked="() => vm.DoSomething()"/>
이 점이 작게 보이지만, 코드 편집할 때, XAML, 코드 비하인드, 뷰모델 파일을 동시에 열어 놓게 만들 확률이 높습니다.
따라서, 제시하신 세 가지 방법 중 어떤 것을 선택하더라도 개발하는 과정에서는 큰 차이가 없게 됩니다.
다만, 개인적 코딩 스타일이 이벤트 핸들러보다는 Command 를 선호한다면 XAML+뷰모델 위주로 편집할 확률이 높아지므로 식별자를 XAML에 두는 편이 좋을 것입니다.
반대인 경우, 코드 비하인드에 넣는 편이 더 유리할 것 같습니다.
readonly LoginViewModel _vlewModel;
public LoginView()
{
InitializeComponent();
// LoginViewModel 은 참조형식
DataContext = _viewModel = new LoginViewModel();
}
void OnStartButtonClicked(object? s, EventArgs e)
{
//
}
1 Like
아메리카노
6
public LoginView()
{
// XAML 요소의 DataContext attribute로부터 DataContext 속성 설정됨.
InitializeComponent();
// 재설정 => 최종적인 설정.
DataContext = Bootstrapper.ServiceProvider.GetService<LoginViewModel>();
// DataContext = new LoginViewModel();
}
해당 내용이 xaml의 DataContext에서 ViewModel을 설정한 후 코드 비하인드에서 다시 설정하는건가요? 이렇게 하는 이유를 잘 모르겠습니다.
식별자를 xaml에 두는 것은 xaml의 Datacontext에서 Viewmodel을 설정하는게 맞나요??
WPF (나 기타 XAML 기반 UI 프레임워크)를 계속 사용할 것이면, InitializeComponent() 메서드가 왜 호출되는 지 알아 두시는 것이 좋을 것 같습니다.
예 맞습니다. 그것을 보고 바인딩된 객체의 형식을 알 수 있는 것이죠.