sample: https://github.com/Microsoft/Appsample-Photosharing

 

PhotoSharingApp 에서는 ViewModel 객체를 생성할 때,
대부분의 경우 아래와 같은 형태로 ViewModel을 생성합니다.(CategoriesPage.xaml.cs)
---------------------------------------------------------------------
ServiceLocator.Current.GetInstance<CategoriesViewModel>(loadData);
---------------------------------------------------------------------
위와 같은 코드를 통해 return 되는 값은 CategoriesViewModel 객체입니다.
위 처럼 하여 ViewModel 객체를 얻을 수 있는 이유는,
UnityBootstrapper 내에서 UnityContainer 내부에 우리가 사용하게 될 ViewModel Type들을
Register 해두었기 때문입니다.(ViewModelRegistry.cs 에서 확인 가능)


그런데 이때 궁금한 점이 생겼습니다.
A page 가 존재할 때, A Page 입장에서는 아래와 같은 두 경우로 A Page에 올 수 있습니다.

1. 안드로이드 앱처럼, 현재 보던 A Page에서 B Page로 잠시 이동하였다가,Back으로 다시 돌아오는 경우.
2. B page에서 A Page로 바로 들어오는 경우. (새롭게 A Page가 생성되는 경우)

궁금한 점은, Back으로 돌아온 경우, 기존에 보던 A Page의 내용이 보존되어야 할 것입니다.
즉 다르게 말해서 ViewModel이 유지되고 있어야 함을 의미한다고 할 수 있습니다.

Back이 아닌, B page에서 A page로 바로 들어오는 경우는? 특별히 기존 데이터를 보존할 필요가 없는 경우이므로
새롭게 viewModel을 new 해주면 해결이 되겠지요..


그럼 여기서 어떻게 1,2번의 경우에 대해 처리를 해주고 있을까요?
맨 위로 돌아가면, 우리의 예제에서는 코드 비하인드에서
ServiceLocator.Current.GetInstance<CategoriesViewModel>(loadData);

위와 같이 viewModel을 얻고있는데, 어떻게 위의 1,2번 모두를 한줄로 알아서 관리가 되는걸 까요?


-----------------------------------------------------------------------
Unity 는 어떻게 위와 같은 상황을 관리하고 있는가.

정리

1. Unity를 쓰는 프로젝트에서는 ServiceLocator.current.GetInstance 를 통해 viewModel을 얻는다.
2. viewModel을 얻을 때, 내가 원하는 형태를(1,2번) flag 값을 전달하여 구분시켜 준다.(loadData)
3. UnityBootStrapper 내부에서 Container를 가지고 있는데, 해당 Container에
  우리 프로젝트에서 사용되는 ViewModel 들을 register 하게 된다.
  이 때, register를 하면서 내부적으로 getInstance가 호출 될 때,
 
  - viewModel을 매번 새롭게 생성해줄지
  - 내부적으로 singleton으로 관리하여 동일한 객체를 매번 return 할지.

  LifetimeManager 라는 객체(정책을 가지고있음)를 같이 등록하여 가능하게 만듭니다.
  (원하는데로 ViewModel , service 등등
  UnityContainer에 등록할 때 함께 등록한 Lifetimemanager가 가지고있는 정책에 맞게
  getInstance()가 동작합니다.)


정리한 내용이 좀 어렵지요?

간략히 요점만 정리하면,

우리는 UnityContainer에 viewModel, view, Service 따위를 등록해놓고
GetInstance(type) 형태로 전달받아 쓰게되는데 ,
등록할 때, LifeTimemanager를 함께 등록함으로써,
A page -> B page -> back 을 했을 때
viewModel이 singleton으로 관리되어
A Page의 ViewModel이 유지되도록 한다.

위와 같은 방법으로 기존 데이터가 유지될 수 있도록 합니다.

-------------------------------------------------------------------------------------

위 예제로 돌아가서 실제 코드를 보고 확인해볼까요?

(1단계)

-VieModelRegistry.cs-
Container.RegisterType<CategoriesViewModel>(new ContainerControlledLifetimeManager());

위와 같이 우리가 사용할 viewModel을 Container에 등록하면서,
기본적으로는 Container가 viewModel 객체를 Singleton으로 관리할 수 있도록
lifeTimemanager를 ContainerControlledLifeTimeManager와 함께 등록해놓습니다.

(2단계)

-CategoriesPage.xaml.cs-
OnNavigatedTo()
{
            var loadData = e.NavigationMode != NavigationMode.Back;
            _viewModel = ServiceLocator.Current.GetInstance<CategoriesViewModel>(loadData);
            DataContext = _viewModel;

            if (loadData)
            {
                await _viewModel.LoadState();
            }

}


위 처럼, Back으로 돌아온 경우, 최근에 해당 view의 viewModel을 그냥 쓰면 되기 때문에
loadData flag의 값은 false로 전달하게 됩니다.

반대로, Back이 아닌경우, loadData 값이 True가 되기 때문에
GetInstance() 메소드를 통해 리턴된 값은 새롭게 new 생성한 CategoriesVieModel 객체입니다.

텅텅 비어있는 새 viewModel 이기 때문에, 원하는 값을 채워놔야 되겠지요??

이 때는, 미리 viewModel에 override 해놓은 LoadState() 메소드를 호출하여,
원하는 값으로 viewModel 내용을 채워넣으면 됩니다.

해당 내용을 채워넣을 source는, OnNavigatedTo() 를 호출하는
NavigationFacade 쪽에서 만들어준 args 를 참고하여 내용을 채울수도 있습니다.

---------------------------------------------------------------------

여기까지 마.쏘의 uwp 샘플인 PhotoSharingApp 프로젝트와 함께보는
ServiceLocator의 객체 관리 정책과 view 전환에 따른 viewModel 유지 방법에 대해 알아보았습니다.

 

'WPF,UWP' 카테고리의 다른 글

[UWP] 개념 With PhotoSharing 샘플예제  (0) 2016.10.18
블로그 이미지

kuku_dass

,