사용법
실제 샘플 프로젝트 기반으로 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/SampleCoreSampleSmart — 스마트 패턴 + 스레딩
커맨드 본문까지 생성기에 맡기는 축약 패턴입니다. [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/SampleSmartSampleEnterprise — 모듈 분리 아키텍처
규모가 커지면 레이어를 프로젝트 단위로 분리합니다. 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/SampleEnterpriseSample01 — 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/Sample01SampleCrossUi — 하나의 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