Skip to main content

Command Palette

Search for a command to run...

[MVVM] ViewModel에서 View 참조

Updated
2 min read

응용 애플리케이션을 만들 때 MVVM 패턴을 적용하면 뷰와 뷰에 데이터를 전달하는 뷰모델 간 책임을 분리할 수 있습니다.

대부분의 경우 데이터 바인딩을 통해 뷰모델의 데이터를 뷰에 표시하고 갱신할 수 있습니다.

그런데 MVVM에서 명령어를 뷰모델에서 처리할 때 뷰의 동작이 필요할 때가 있습니다.

예를 들어보겠습니다.

화면상에서 텝에 새로운 컨텍스트가 추가될 때 컨텍스트의 이름을 설정해야 하고 이 이름을 팝업 윈도우를 통해 입력 받아야 한다고 가정해 봅시다.

  1. [뷰] 텝 추가 버튼 클릭
  2. [뷰모델] 컨텍스트 추가
    1. [뷰] 컨텍스트 이름 팝업 입력
    2. [뷰모델] 입력받은 이름으로 컨텍스트 추가
  3. [뷰] 컨텍스트 바인딩에 의해 탭 표시, 내용 표시...

다른 과정은 데이터 바인딩을 통해 가능한데 '2-1'의 경우 뷰모델에서 뷰의 메서드를 호출해야만 합니다. 하지만 뷰모델에서 뷰를 참조하게 되면 MVVM 패턴에 위반됩니다. 이를 SOLID 원칙 의존관게 역전 원칙을 사용하면 해결됩니다. 이는 IoC에서도 동일한 원리로 사용됩니다.

이를 위해 뷰모델은 뷰를 그대로 참조하지 않고 인터페이스로 참조해서 뷰는 그 인터페이스를 구현하고 뷰모델은 인터페이스로 참조하는 것으로 직접적인 뷰모델과 뷰간 참조 관계가 없도록 합니다.

인터페이스로 관계 명세

간단한 두개의 인터페이스로 시작합니다.

public interface IViewAction
{
}

public interface IHaveViewAction<TViewAction>
    where TViewAction : IViewAction
{
    TViewAction? ViewAction { get; set; }
}

IViewAction은 뷰 액션을 의미하며 IHaveViewAction의 제네릭 인자가 뷰 액션임을 나타냅니다. IHaveViewAction<TViewAction>은 뷰가 뷰 액션을 소유함을 의미하며 다음처럼 사용할 수 있습니다.

| 뷰모델

public partial class RepositoryViewModel : ObservableRecipient, IViewModel, IHaveViewAction<IRepositoryViewAction>
{
    public IRepositoryViewAction? ViewAction { get; set; }
...

IViewModel도 해당 클래스가 뷰모델임을 나타내는 빈 인터페이스입니다.

뷰는 다음의 모습이 됩니다.

| 뷰

public sealed partial class RepositoryPage : ViewModelPage, IView<RepositoryViewModel>, IRepositoryViewAction
{
    public RepositoryPage()
    {
        InitializeComponent();

        ViewModel.ViewAction = this;
    }
...

이제 RepositoryPageIRepositoryViewAction 인터페이스를 구현하는 것으로 뷰모델에서 MVVM 패턴을 해치지 않으면서 뷰의 기능을 사용할 수 있게 됩니다.

35 views

More from this blog

개발, 테스트, 운영에서의 도커 활용

핵심 원칙: "한 번 빌드하고, 어디서든 실행한다 (Build once, run anywhere)" 도커의 가장 큰 장점은 환경 일관성입니다. 동일한 도커 이미지를 사용하여 개발, 테스트, 운영 환경을 구성함으로써 "제 PC에서는 됐는데..." 하는 문제를 최소화할 수 있습니다. 1. 개발 단계 (Development) 목표: 빠른 코드 변경 반영, 쉬운 디버깅, 실제 운영 환경과 유사한 환경 구성. Docker 사용 방안: Dockerf...

May 9, 20256 min read15

[EF Core] 데이터 삭제 시 소프트 삭제 적용

DB에서 데이터를 삭제하면 일반적으로 복구할 수 없습니다. 또한 관계에 따라 영구 삭제 자체가 어려울 수도 있습니다. 그래서 데이터를 영구 삭제하는 대신 IsDeleted 속성을 true로 주고 IsDeleted 속성을 필터링해서 조회하는 방법을 사용하기도 합니다. 이를 소프트 삭제라고 합니다. 그런데 EF에서 알아서 데이터 삭제 시 소프트 삭제를 하고 쿼리시 IsDeleted 속성을 체크해서 삭제한 데이터를 제외한 데이터만 쿼리하게 하는 ...

Mar 18, 20243 min read19

[EF Core] ValueConverter를 이용해서 엔터티 속성의 도메인 관리

EF Core를 사용하면서 문자열 길이 등의 특성을 일일이 지정하는 것은 번거롭습니다. ... [MaxLength(32)] public string? 제목 { get; set; } 엔터티가 한 개일 때는 상관이 없으나 제목 유형이 여러 엔터티에 사용될 경우 유형을 지정하기 번거롭습니다. 속성 유형을 도메인으로 관리하면 참 편할텐데요, ValueConverter를 이용할 수 있습니다. 그런데 이것을 인터페이스 정적 추상를 사용해서 다음처럼 ...

Mar 16, 20242 min read8

디모이 블로그

154 posts

.NET 관련 기술을 선호하고 새로운 언어를 배우는데 관심이 있습니다.