LazyRegion 컨트롤을 만들어봤어요.

LazyRegion.WPF은 WPF (Windows Presentation Foundation) 라이브러리로, ContentControl의 내용이 바뀔 때 즉각적인 전환 대신 부드러운 애니메이션 효과를 제공합니다. 기존 ContentControl은 콘텐츠가 변경되면 화면이 즉시 바뀌지만, LazyRegion.WPF은 페이드, 슬라이드 등 다양한 애니메이션을 통해 자연스럽고 시각적으로 매력적인 전환을 구현합니다. 이 라이브러리는 코드 비하인드, MVVM, 그리고 RegionManager를 통한 동적 콘텐츠 관리 등 다양한 개발 환경에 최적화되어 있습니다.


주요 특징

  • :film_frames: 애니메이션 전환 지원: 설정한 애니메이션 효과와 속도에 맞춰 콘텐츠를 자연스럽게 변경합니다. 다양한 전환 효과(예: Fade, SlideLeft, ZoomIn)를 지원합니다.

  • :puzzle_piece: MVVM 친화적: ViewModel의 변경을 자동으로 감지하여 뷰를 전환합니다. 데이터 템플릿을 사용하여 ViewModel에 따라 다른 화면을 자동으로 표시할 수 있습니다.

  • :laptop: 코드 비하인드 친화적: 코드 비하인드에서 Content 속성 값을 직접 변경하더라도 동일한 애니메이션 효과가 적용됩니다.

  • :package: RegionManager 지원: RegionManager를 통해 미리 지정된 영역(Region)에 동적으로 화면을 주입하거나 변경할 수 있어, 모듈화된 애플리케이션 개발에 유용합니다.


사용 예시

MVVM 친화적

LazyRegion.WPFCurrentViewModel 속성에 바인딩되어 ViewModel이 변경될 때마다 데이터 템플릿에 따라 다른 화면을 표시하고 애니메이션을 적용합니다.

<Window.Resources>
    <DataTemplate DataType="{x:Type vm:AViewModel}">...</DataTemplate>
    <DataTemplate DataType="{x:Type vm:BViewModel}">...</DataTemplate>
</Window.Resources>

<Grid>
    <wpf:LazyRegion Content="{Binding CurrentViewModel}" TransitionAnimation="{Binding SelectAnimationType}" />
    <Button Command="{Binding GoCommand}" Content="변환" />
</Grid>

RegionManager 지원

App.xaml에서 LazyRegion.WPF을 활성화하고 뷰를 등록한 후, RegionManager를 통해 특정 영역(Region)에 원하는 뷰를 동적으로 로드할 수 있습니다.

// App.xaml.cs에서 DI 등록
serviceCollection.UseLazyRegion();
serviceCollection.AddLazyView<AControl>("a");
serviceCollection.AddLazyView<BControls>("b");

// RegionManager를 통해 "Root" 영역에 "a" 키를 가진 뷰를 로드
this._lazyRegionManager.NavigateAsync("Root", "a");

이처럼 LazyRegion은 WPF 애플리케이션의 사용자 경험을 향상시키는 데 효과적인 도구입니다.


앞으로

시간 나는 대로 데모 영상과 샘플 프로젝트도 공유하겠습니다.
궁금한 점이나 피드백은 댓글로 남겨주세요! :blush:

레포지토리

15개의 좋아요

Animation 전환 데모 영상

향후 계획

  • 샘플 프로젝트 공유
  • 화면1, 2에 대한 애니메이션을 커스텀할 수 있게 StoryBoard로 제공 기능 구현 예정
10개의 좋아요

샘플 프로젝트 공유

안녕하세요.

각 프로젝트 샘플 방식에 대해 간단히 설명해드리겠습니다!

  • CodeBehind 방식

    • 설명: 뷰(View)의 코드 비하인드 파일에서 UI 로직을 직접 처리하는 전통적인 방식입니다.

    • 주요 활용: WPF 기본 문법 학습, 소규모 프로젝트, LazyRegion과 같은 특정 라이브러리 연동 테스트 등.

  • DataTemplate 기반 방식

    • 설명: DataTemplate을 활용해 데이터 모델에 따라 UI를 동적으로 생성하는 방식입니다.

    • 주요 활용: 유연하고 재사용성이 높은 UI 컴포넌트 구성이 필요한 경우.

  • LazyRegionManager (View Injection 방식)

    • 설명: LazyRegionManager를 사용해 뷰를 특정 영역(Region)에 동적으로 삽입하는 방식입니다. 뷰 로직이 뷰에 종속되어 있어, 뷰 중심의 개발에 적합합니다.

    • 주요 활용: ViewModel을 사용하지 않고 View 간의 결합도를 낮춰야 하는 경우.

  • LazyRegionManager (ViewModel Injection 방식)

    • 설명: LazyRegionManager를 통해 View의 고유키를 호출하여 View를 띄어주는방식입니다.
    • 주요 활용: MVVM 패턴 기반의 대규모 프로젝트나, 로직의 테스트 용이성을 확보해야 하는 경우.

개발 방식은 프로젝트의 규모와 팀의 스타일에 따라 달라질 수 있습니다. 각 방식의 장단점을 이해하고 프로젝트에 가장 적합한 방식을 선택하는 것이 중요합니다.


p.s LazyRegionManager의 ViewModel Injection방식에는 앞으로 더 개발할 것이 있습니다.

  • View ←> ViewModel 자동맵핑 기능(App 세팅 당시 Mapper 설정해야함)
  • 뷰모델 타입을 선언해줌으로써 View, ViewModel을 바인딩 처리해주는 기능
    • ex) this._lazyRegionManager.NavigateAsync<뷰모델 타입>(리전 이름, 뷰 키 이름)
7개의 좋아요

LazyRegion.WPF 1.1.0 기능 업데이트

1. 초기 네비게이션 구성 (ConfigureInitialNavigation)

  • 앱 시작 시 특정 Region으로 자동 화면 이동 설정 가능.

  • configure.NavigateAsync("RegionName", "ViewKey") 형태로 사용.

사용 예시

serviceCollection.UseLazyRegion()
                 .AddLazyView<ScreenA>("a")
                 .AddLazyView<ScreenB>("b")
                 .ConfigureInitialNavigation(configure =>
                 {
                     configure.NavigateAsync("Root", "a"); // 앱 시작 시 Root Region에 ScreenA 이동
                 });


2. Region Timeout

  • NavigateAsync는 기본적으로 Region 등록될 때까지 무제한 대기.

  • TimeSpan을 사용해 대기 시간을 설정 가능.

  • 지정 시간 내 Region이 등록되지 않으면 자동으로 네비게이션 취소.

사용 예시

regionManager.NavigateAsync("Root", "a", new TimeSpan(0, 0, 30)); // 30초 동안 대기 후 취소

6개의 좋아요

LazyRegion.WPF 1.2.0 기능 업데이트

RegionControl에 상태 기반 화면 관리 기능(RegionState)이 새롭게 추가되었습니다.
이제 각 Region은 자동으로 LoadingError 상태 화면을 처리할 수 있습니다.

주요 기능

  • 지정된 시간 동안 표시되는 Loading 화면
  • 설정된 시간이 지나도 해당 Region에 변화가 없을 경우 자동으로 표시되는 Error 화면
  • Error 상태 이후에도 ViewKey 변화 시 정상적으로 화면 전환 가능

이 기능을 통해 Region 단위의 상태 관리가 더욱 단순하고 직관적으로 개선되었습니다.


지정 된 시간 초과 시 에러 화면 노출

지정 된 내 시간 내 리전에 화면 전환


기대효과

기존에는 API 요청 전후로 Region.NavigateAsync()를 직접 호출하여 “로딩 화면 → 실제 화면”으로 전환해야 했습니다.
RegionState 도입 후에는 이러한 제어 로직을 ViewModel에서 제거하고, Region 자체가 자동으로 로딩/에러 상태를 관리합니다.

Before

// ViewModel 내부
public async Task LoadAsync()
{
    await _regionManager.NavigateAsync("MainRegion", "LoadingView");
    
    var result = await _api.GetDataAsync();

    if (result.IsSuccess)
        await _regionManager.NavigateAsync("MainRegion", "DataView");
    else
        await _regionManager.NavigateAsync("MainRegion", "ErrorView");
}

After

// ViewModel 내부
public async Task LoadAsync()
{
    var result = await _api.GetDataAsync();

    if (result.IsSuccess)
        await _regionManager.NavigateAsync("MainRegion", "DataView");
}
8개의 좋아요

LazyRegion.Maui 라이브러리도 출시해봤습니다.

MAUI는 기본적으로 Page 기반의 네비게이션을 사용하기 때문에 LazyRegion.Maui의 사용이 다소 의문스러울 수 있습니다.

하지만 이런 경우가 있습니다.

이런 경우가 있을겁니다.
Shell, TabbedPage 에서는 자유롭게 페이지를 생성하고 네비게이션할 수 있지만,
네비게이션 바 아이콘을 변형하는 등 자유도가 낮아 원하는 UI를 구현하기 어려울 때가 종종 있어, 이럴 때 LazyRegion.Maui를 고려할 수 있습니다.

요즘 앱은 네비게이션 바 자체가 다양하며, Flutter 진영에서는 다양한 네비게이션 바 스타일을 패키지하는 사례도 있습니다.


MAUI에서도 이러한 생태계를 구축할 수 있도록 ContentView 간 전환 기술이 있다면, NavigationBar 디자인만 입히면 자연스럽게 구현되지 않을까 하는 생각입니다.

5개의 좋아요