iconDreamine

사용법

실제 샘플 프로젝트 기반으로 Dreamine 사용법을 소개합니다. 모든 샘플은 저장소의 998. DEMO/000. Sample 폴더에 있으며, 그대로 빌드해서 실행할 수 있습니다.

시작하기

WPF 프로젝트에 Dreamine.MVVM.FullKit 패키지를 추가하고 App 클래스에 [DreamineEntry] 하나만 붙이면 됩니다. DI 컨테이너 초기화, ViewModel 자동 등록, View/ViewModel 매핑, ViewManager 등록까지 Source Generator가 전부 만들어 줍니다.

using Dreamine.MVVM.Attributes;
using System.Windows;

namespace MyApp
{
    [DreamineEntry]   // 이 한 줄로 부트스트랩 완료 (bootstrap done with this single line)
    public partial class App : Application
    {
    }
}

SampleCore — WPF MVVM 기본

Dreamine의 기본 구조는 Model(상태) / Event(로직) / ViewModel(바인딩)의 3분할입니다. ViewModel은 [DreamineModel]·[DreamineEvent] 필드 선언만으로 자동 주입되고, [DreamineCommand]가 ICommand 프로퍼티를 생성합니다.

public partial class MainWindowViewModel : ViewModelBase
{
    [DreamineModel] private MainWindowModel _model;   // 상태 (state)
    [DreamineEvent] private MainWindowEvent _event;   // 로직 (logic)

    public string Title   => Model.Title;
    public string Message => Model.Message;

    [DreamineCommand] private void Ok()      => Event.Ok();      // → OkCommand
    [DreamineCommand] private void Cancel()  => Event.Cancel();  // → CancelCommand
    [DreamineCommand] private void SubPage() => Event.SubPage();
}

화면 이동·창 제어 같은 실제 로직은 Event 클래스에 둡니다. IViewManager를 생성자에서 주입받아 다른 View를 띄웁니다.

public class MainWindowEvent
{
    private readonly IViewManager _viewManager;
    public MainWindowEvent(IViewManager viewManager) => _viewManager = viewManager;

    public void Ok()      => MessageBox.Show("확인 클릭됨!");
    public void SubPage() => _viewManager.Show<PageSubViewModel>();  // 화면 이동
}
998. DEMO/000. Sample/010. Wpfs/SampleCore

SampleSmart — 스마트 패턴 + 스레딩

커맨드 본문까지 생성기에 맡기는 축약 패턴입니다. [DreamineCommand("Event.Ok")] + partial 메서드 선언만 하면 포워딩 코드가 자동 생성됩니다. View 옆에 MainWindow.xaml.ViewModel.cs처럼 파일을 붙여 두는 코로케이션 구조와, IDreamineThreadManager를 이용한 백그라운드 잡 등록도 이 샘플에서 볼 수 있습니다.

public partial class MainWindowViewModel : ViewModelBase
{
    [DreamineModel] private MainWindowModel _model;
    [DreamineEvent] private MainWindowEvent _event;

    // 본문 없는 partial 선언 → Event.Ok()로 포워딩하는 코드가 자동 생성
    [DreamineCommand("Event.Ok")]      private partial void Ok();
    [DreamineCommand("Event.SubPage")] private partial void SubPage();

    public MainWindowViewModel(IDreamineLogger logger, IDreamineThreadManager threads)
    {
        threads.Register(
            new DreamineThreadOptions { Name = "MonitoringJob", IntervalMs = 10, AutoStart = true },
            async token => { /* 주기 실행 작업 (periodic work) */ });
    }
}
998. DEMO/000. Sample/010. Wpfs/SampleSmart

SampleEnterprise — 모듈 분리 아키텍처

규모가 커지면 레이어를 프로젝트 단위로 분리합니다. Models / Events / ViewModels / Views / Styles / Resources를 각각 독립 프로젝트로 나눠도 [DreamineEntry] 부트스트랩은 동일하게 동작합니다. 팀 단위 분업과 참조 방향 강제가 필요할 때 이 구조를 사용하세요.

SampleEnterprise/               ← 진입점 ([DreamineEntry] App)
SampleEnterprise.Models/        ← 상태
SampleEnterprise.Events/        ← 로직
SampleEnterprise.ViewModels/    ← 바인딩
SampleEnterprise.Views/         ← XAML 화면
SampleEnterprise.Styles/        ← 공용 스타일
SampleEnterprise.Resources/     ← 리소스(문자열·이미지)
998. DEMO/000. Sample/010. Wpfs/Enterprise/SampleEnterprise

Sample01 — WPF + Blazor 하이브리드

WPF 앱 안에서 Blazor Server를 함께 띄우는 구조입니다(이 사이트도 같은 방식으로 동작합니다). AddDreamineHybridWpf()와 AddDreamineBlazorServer<AppShell>()를 등록하면 WPF 창과 웹 UI가 하나의 프로세스에서 실행되고, IHybridStateStore로 상태를 공유하며 IHybridMessageBus로 양방향 메시지를 주고받습니다.

[STAThread]
public static void Main()
{
    var builder = Host.CreateApplicationBuilder();

    builder.Services.AddDreamineHybridWpf();
    builder.Services.AddSingleton<MainWindow>();

    // WPF ↔ Blazor 공유 상태
    builder.Services.AddSingleton<IHybridStateStore<CounterState>>(
        new HybridStateStore<CounterState>(new CounterState(0, "-", null)));

    builder.Services.AddDreamineBlazorServer<AppShell>(options =>
    {
        options.Port = 5000;
        options.SharedServiceTypes.Add(typeof(IHybridStateStore<CounterState>));
    });

    builder.Build().RunDreamineWpfApp<App>();
}

Blazor 쪽 ViewModel은 요청만 발행하고, 실행과 상태 소유는 WPF 쉘이 담당합니다.

public sealed class IndexViewModel
{
    private readonly IHybridMessageBus _bus;
    public IndexViewModel(IHybridMessageBus bus) => _bus = bus;

    // Blazor는 요청만 발행 — 실행은 WPF 쉘이 담당
    public Task OpenProjectAsync() =>
        _bus.PublishAsync(new DashboardActionRequestedMessage(DashboardAction.OpenProject));
}
998. DEMO/000. Sample/040. Hybrids/Sample01

SampleCrossUi — 하나의 ViewModel, 4개의 UI

UI에 의존하지 않는 ViewModel을 Shared 프로젝트에 한 번 작성하면 WPF · WinForms · Blazor · .NET MAUI에서 수정 없이 그대로 재사용됩니다. 로직은 Event 클래스에 있고 ViewModel은 [DreamineCommand] 포워딩과 읽기 전용 상태만 노출합니다.

// Shared 프로젝트에 한 번만 작성 — WPF·WinForms·Blazor·MAUI에서 그대로 사용
public partial class CounterViewModel : ViewModelBase
{
    [DreamineEvent] private CounterEvent _event;

    public int Count => Event.Count;
    public ObservableCollection<CounterLogItem> Logs => Event.Logs;

    [DreamineCommand("Event.Increment")] private partial void Increment();
    [DreamineCommand("Event.Reset")]     private partial void Reset();
}
998. DEMO/000. Sample/050. CrossUi