iconDreamine

How to Use

Learn Dreamine through real sample projects. All samples live in the 998. DEMO/000. Sample folder of the repository and build & run as-is.

Getting Started

Add the Dreamine.MVVM.FullKit package to your WPF project and put a single [DreamineEntry] on your App class. The source generator emits everything else — DI container setup, automatic ViewModel registration, View/ViewModel mapping, and ViewManager registration.

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

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

SampleCore — WPF MVVM Basics

Dreamine splits a screen into three parts: Model (state), Event (logic), and ViewModel (binding). Fields marked [DreamineModel] and [DreamineEvent] are injected automatically, and [DreamineCommand] generates ICommand properties.

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();
}

Actual logic such as navigation and window control lives in the Event class. Inject IViewManager via the constructor to show other views.

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 — Smart Pattern + Threading

A condensed pattern that delegates even the command body to the generator: declare a partial method with [DreamineCommand("Event.Ok")] and the forwarding code is generated. This sample also shows the colocation layout (MainWindow.xaml.ViewModel.cs next to the view) and background job registration with 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 — Modular Architecture

As the app grows, split layers into separate projects: Models / Events / ViewModels / Views / Styles / Resources. The [DreamineEntry] bootstrap works unchanged. Use this layout when you need team-level ownership and enforced reference direction.

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 Hybrid

Runs a Blazor Server inside a WPF app — this very site works the same way. Register AddDreamineHybridWpf() and AddDreamineBlazorServer<AppShell>() to run the WPF window and the web UI in one process, share state via IHybridStateStore, and exchange messages via 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>();
}

The Blazor-side ViewModel only publishes requests; execution and state ownership stay in the WPF shell.

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 — One ViewModel, Four UIs

Write a UI-independent ViewModel once in a Shared project and reuse it unmodified across WPF, WinForms, Blazor, and .NET MAUI. Logic lives in the Event class; the ViewModel exposes only [DreamineCommand] forwarders and read-only state.

// 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