MVVM에서 상태를 관리하기위한 좋은 공식 패턴이 있습니까?


21

웹 세계에서 Redux 및 React에 대해 배우기 시작했으며 WPF의 MVVM 스타일 아키텍처를 사용하여 데스크톱 세계에서 고통스러운 상태 관리가 얼마나 고통스러워하는지 알 수 있습니다 (Caliburn을 사용하여 뷰를 바인딩하는 방법) ViewModels에).

Redux에는 상태를 관리하는 방법을 결정하는 몇 가지 간단한 원칙이 있으며 UI 업데이트, 이벤트 처리 및 상태 변경을 훨씬 더 예측 가능하게 만듭니다. 원칙은 다음과 같습니다.

  • 단일 진실 소스 (모든 변경 가능한 상태는 단일 공유 객체에 저장 됨)
  • 상태는 읽기 전용입니다. 일반적으로 WPF에서 발생하는 코드 전체에서 구성 요소로 수정할 수 없습니다.
  • 상태는 순수한 함수로만 수정할 수 있습니다.

WPF의 MVVM 아키텍처를 사용하면 대화식 뷰를 매우 빠르게 작성할 수 있지만 다양한 뷰 모델과 이벤트가 모두 변경 될 때 디버깅 문제가 악몽입니다. 예를 들어,보기를 변경하고 기본 탭을 설정하려고 시도한 이벤트가 발생했지만 웹 서비스에서 데이터가 비동기식으로로드되지 않아 탭이 존재하지 않아 (아직) 아무 일도 일어나지 않습니다.

나는 서로를 업데이트하는 상호 관련 viewModels 구성 요소 간의 복잡한 상호 작용을 이해하고 이해하기 위해 다이어그램을 그리는 데 시간을 보냈습니다.

Redux는이 상태의 일부 예측 불가능 성을 해결하는 것을 목표로하고 있습니다. 상태를 더 잘 관리하는 데 도움이되는 WPF와 잘 어울리는 유사한 또는 아키텍처 패턴이 있습니까? 아직 시도하지 않았기 때문에 Redux 원칙이 .NET에서 얼마나 잘 작동하는지 잘 모르겠습니다. 아마도 누군가 조언을 줄 수있는 경험이 있습니까?


브라우저에서도 비슷한 문제가 있습니다. 간단한 Javascript가 너무 빨리 실행되고 DOM이 아직 빌드되지 않았으므로 UI ​​요소를 찾을 수 없습니다. 다행히도 여러 가지 이벤트가 있으므로 다른 일이 더 진행될 때까지 일부 스크립트의 실행 지연을 트리거하는 데 사용할 수 있습니다. (DOMContentLoaded와 동일)
Erik Eidt

1
redux의 상태는 실제로 업데이트되며 절대 수정되지 않습니다.
Andy

1
나는 파티에 늦었다는 것을 알고 있지만 Redux 아키텍처를 .NET에 가져 오는 React.NET 이라는 프로젝트가 있습니다.
SiberianGuy

Angular 프로젝트에서 ngrx / store 의 접근 방식을 좋아하는 사람들을 위해 ngrx / store 에서 영감을 얻은 .Net 프로젝트에 대한 NetRx.Store 상태 관리가 있습니다. Nuget 에서도 찾을 수 있습니다 . 또한 사용의 좋은 샘플이 WPF 프로젝트에서 MVVM 패턴 NetRx.Store은
Vitalii 첸코

답변:


8

무슨 말인지 알 것 같아 기본적으로 '컨트롤러'또는 '마스터'뷰 모델을 추가하여 문제를 해결합니다 (예비 의사 코드).

public class MasterVM
{
    public ChildVM View1 {get;set;}
    public ChildVM View2 {get;set;}

    private Data data;
    public MasterVM()
    {
        View1.OnEvent += updateData;
    }

    private Action<int> updateData(int value)
    {
         View2.Value = value;
    }
}

중재자 패턴으로이 작업을 수행 할 때 클래스를 컨트롤러라고 생각합니다. 즉.

public class Controller
{
    public Controller(MediatorService m)
    {
        m.Subscribe("valueupdated", updateData);
    }

    private Action<int> updateData(int value)
    {
         m.Publish("showvalue", value);
    }
}

public class View2
{
    public View2(MediatorService m)
    {
        m.Subscribe("showvalue", (int v)=> {Value = v;});
    }
}

이런 종류의 것을 사용하면 '흐름 논리'또는 이벤트 오케스트레이션을 이러한 높은 수준의 지속 클래스에 배치하고 VM 코드를 가볍게 유지할 수 있습니다. '사용자가 구매를 클릭하면 주문이 처리됩니다'라는 주문을 변경하려는 경우 'OrderFlowController'또는 'OrderProcessVM'에서 확인하거나 이름을 지정하려고합니다. BasketVM, PaymentVM, 3dSecureVM 등의 조합이 아닌

따라서 '탭이 아직 준비되지 않았습니다'라는 구체적인 예에서

public class Controller
{
    bool dataLoadCompleted;
    public Controller(MediatorService m)
    {
        m.Subscribe("setTabRequest", setTab); //message from view model with set tab button
        m.Subscribe("dataLoadComplete", dataLoadComplete); //message from data loading view model or some other controller?
    }

    private Action<int> setTab(int value)
    {
         if(!dataLoadCompleted)
         {
             m.Publish("error", "Please wait for data to load"); //message for error alert view model
         }
         else
         {
             m.Publish("setDefaultTab", value); //message for tab viewmodel
         }
    }

    private Action dataLoadComplete()
    {
         //persist state;
         dataLoadCompleted = true;
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.