iconDreamine

Playground

Try Dreamine MVVM in the browser; review WPF/WinForms/MAUI through real screenshots or videos.

Light Bulb — Button & Checkbox

A button (command) and a checkbox (two-way binding) drive the same state. Logic in Event, state in Model, exposure in ViewModel.

OFF
Toggled 0x
Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<DreamineLightBulb IsOn="@Bulb.IsOn" Diameter="120" />
<DreamineButton Variant="DreamineButtonVariant.Primary" OnClick="Bulb.Toggle">Toggle</DreamineButton>
<DreamineCheckBox @bind-Checked="Bulb.IsOn">Power</DreamineCheckBox>
<span>@Bulb.StatusText · toggled @Bulb.ToggleCount times</span>
public sealed class LightBulbModel { public bool IsOn; public int ToggleCount; }

public sealed class LightBulbEvent
{
    private readonly LightBulbModel _m;
    public LightBulbEvent(LightBulbModel m) => _m = m;
    public void Toggle() { _m.IsOn = !_m.IsOn; _m.ToggleCount++; }
}

public sealed class LightBulbViewModel : ViewModelBase
{
    public bool IsOn { get; set; }
    public int ToggleCount { get; }
    public string StatusText => IsOn ? "ON" : "OFF";
}

Button — DreamineButton

A command-bound button. Each click increments the count and appends a log via the Event.

Clicks 0
Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<DreamineButton Variant="DreamineButtonVariant.Primary" OnClick="Vm.ClickMe">Primary</DreamineButton>
<DreamineButton OnClick="Vm.ClickMe">Secondary</DreamineButton>
<DreamineButton Variant="DreamineButtonVariant.Danger" OnClick="Vm.ClickMe">Danger</DreamineButton>
<span>Clicks @Vm.ClickCount</span>
@foreach (var line in Vm.ActivityLog) { <li>@line</li> }
// Shared ViewModel (Dreamine Source Generator)
[DreamineProperty] private int _clickCount;
public ObservableCollection<string> ActivityLog { get; } = new();

[DreamineCommand]
private void ClickMe()
{
    ClickCount++;
    ActivityLog.Insert(0, $"[{DateTime.Now:HH:mm:ss}] Clicked ({ClickCount})");
}

CheckBox — DreamineCheckBox

IsChecked two-way binding. The last item is disabled (IsEnabled=False).

Check1 = True · Check2 = False

Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<DreamineCheckBox @bind-Checked="Vm.Check1">Check 1</DreamineCheckBox>
<DreamineCheckBox @bind-Checked="Vm.Check2">Check 2</DreamineCheckBox>
<DreamineCheckBox @bind-Checked="Vm.Check3" Disabled="true">Check 3</DreamineCheckBox>
<p>Check1 = @Vm.Check1 · Check2 = @Vm.Check2</p>
[DreamineProperty] private bool _check1 = true;
[DreamineProperty] private bool _check2;
[DreamineProperty] private bool _check3;

RadioButton — DreamineRadioButton

Radios sharing a GroupName; selection passes the value via RelayCommand<string>.

Selected: Option A

Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
@foreach (var opt in new[] { "Option A", "Option B", "Option C" })
{
    <DreamineRadioButton Name="grp" Value="@opt"
                         SelectedValue="@Vm.SelectedRadio"
                         SelectedValueChanged="Vm.SelectRadio">@opt</DreamineRadioButton>
}
<p>Selected: @Vm.SelectedRadio</p>
[DreamineProperty] private string _selectedRadio = "Option A";

[DreamineCommand]
private void SelectRadio(string option) => SelectedRadio = option;

CheckLed — DreamineCheckLed

Dreamine's signature LED indicator. Bind IsOn / IsPulse (great for equipment status).

IsOn = True · IsPulse = False

Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<DreamineCheckLed IsOn="Vm.LedIsOn" IsPulse="Vm.LedIsPulse" Diameter="34" />
<DreamineButton OnClick="Vm.ToggleLed">ON / OFF</DreamineButton>
<DreamineButton OnClick="Vm.TogglePulse">Pulse</DreamineButton>
<p>IsOn = @Vm.LedIsOn · IsPulse = @Vm.LedIsPulse</p>
[DreamineProperty] private bool _ledIsOn = true;
[DreamineProperty] private bool _ledIsPulse;

[DreamineCommand] private void ToggleLed()   => LedIsOn = !LedIsOn;
[DreamineCommand] private void TogglePulse() => LedIsPulse = !LedIsPulse;

TextBox / PasswordBox — DreamineTextBox

Input controls with Hint (placeholder). Clear via command.

Value:

Length: 0

Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<DreamineTextBox @bind-Value="Vm.TextInput" Hint="Type here..."
                 OnFocus="() => _showKeyboard = true" />
<DreamineButton Size="DreamineButtonSize.Small" OnClick="Vm.ClearText">Clear</DreamineButton>
<p>Value: @Vm.TextInput</p>

@* 가상 키보드는 대상 텍스트박스 바로 아래에 표시 — 시선이 튀지 않게. *@
@if (_showKeyboard)
{
    <DreamineVirtualKeyboard IsVisible="_showKeyboard"
                             Value="@Vm.TextInput"
                             ValueChanged="v => Vm.TextInput = v"
                             OnEnter="() => _showKeyboard = false" />
}

<DreamineTextBox @bind-Value="Vm.Password" IsPassword="true" Hint="Password..." />
<DreamineButton Size="DreamineButtonSize.Small" OnClick="Vm.ClearPassword">Clear</DreamineButton>
<p>Length: @Vm.Password.Length</p>

@code { private bool _showKeyboard; }
[DreamineProperty] private string _textInput = string.Empty;
[DreamineProperty] private string _password  = string.Empty;

[DreamineCommand] private void ClearText()     => TextInput = string.Empty;
[DreamineCommand] private void ClearPassword() => Password  = string.Empty;

ComboBox — DreamineComboBox

ItemsSource / SelectedItem binding.

Selected: Cherry
Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<DreamineComboBox Items="Vm.FruitItems" @bind-SelectedItem="Vm.SelectedFruit" />
<span>Selected: @Vm.SelectedFruit</span>
public string[] FruitItems { get; } =
    { "Apple", "Banana", "Cherry", "Grape", "Mango", "Melon" };

[DreamineProperty] private string _selectedFruit = "Cherry";

Expander — DreamineExpander

Bind IsExpanded to the VM to control expand/collapse from code too.

Expand / Collapse
Any content can go here. IsExpanded = True
Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<DreamineExpander Header="Expand / Collapse" @bind-IsExpanded="Vm.IsExpanded">
    Any content can go here. IsExpanded = @Vm.IsExpanded
</DreamineExpander>
[DreamineProperty] private bool _isExpanded = true;

[DreamineCommand] private void ToggleExpand() => IsExpanded = !IsExpanded;

Numeric — NumericRangeBehavior

Numeric input clamped to 0–100. Slider and number stay in sync.

Value: 50
Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<DreamineNumericSlider @bind-Value="Vm.NumericInput" Min="0" Max="100" />
<span>Value: @Vm.NumericInput</span>
private double _numericInput = 50;
public double NumericInput
{
    get => _numericInput;
    set { _numericInput = Math.Clamp(value, 0, 100); OnPropertyChanged(); }
}

ListBox — DreamineListBox

Select (click) + run a command on double-click (activation).

  • Apple
  • Banana
  • Cherry
  • Grape
  • Mango
  • Melon

Selected: Cherry · (double-click an item)

Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<DreamineListBox Items="Vm.FruitItems"
                 @bind-SelectedItem="Vm.SelectedFruit"
                 OnActivate="Vm.ActivateListItem" />
<p>Selected: @Vm.SelectedFruit · @Vm.ListActivated</p>
public string[] FruitItems { get; } =
    { "Apple", "Banana", "Cherry", "Grape", "Mango", "Melon" };

[DreamineProperty] private string _selectedFruit = "Cherry";
[DreamineProperty] private string _listActivated = "(double-click an item)";

[DreamineCommand]
private void ActivateListItem(string item) => ListActivated = $"Activated: {item}";

Counter — Increment / Reset

The SampleCrossUi counter demo. Increment goes through a service, Reset zeroes the count, and logs accumulate automatically.

0
Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<span class="dw-counter-value">@Vm.Count</span>
<DreamineButton Variant="DreamineButtonVariant.Primary" OnClick="Vm.Increment">Increment</DreamineButton>
<DreamineButton OnClick="Vm.ResetCounter">Reset</DreamineButton>
@foreach (var line in Vm.CounterLogs) { <li>@line</li> }
[DreamineProperty] private int _count;
public ObservableCollection<string> CounterLogs { get; } = new();

[DreamineCommand]
private void Increment()
{
    Count++;
    CounterLogs.Insert(0, $"[{DateTime.Now:HH:mm:ss}] Incremented → {Count}");
}

[DreamineCommand]
private void ResetCounter()
{
    Count = 0;
    CounterLogs.Insert(0, $"[{DateTime.Now:HH:mm:ss}] Counter reset.");
}

DataGrid — DreamineDataGrid

ItemsSource binding + ClickToDeselect Behavior. Displays equipment status in a read-only table.

NoNameStatus
1 Device A Running
2 Device B Stopped
3 Device C Running
4 Device D Error

Selected:

Show the code behind this Live demo
@* @using Dreamine.UI.Blazor *@
<DreamineDataGrid TItem="GridRow" Items="Vm.GridRows" @bind-SelectedItem="Vm.SelectedRow">
    <HeaderContent><th>No</th><th>Name</th><th>Status</th></HeaderContent>
    <RowContent>
        <td>@context.No</td><td>@context.Name</td><td>@context.Status</td>
    </RowContent>
</DreamineDataGrid>
public ObservableCollection<GridRow> GridRows { get; } = new()
{
    new() { No = 1, Name = "Device A", Status = "Running" },
    new() { No = 2, Name = "Device B", Status = "Stopped" },
    new() { No = 3, Name = "Device C", Status = "Running" },
    new() { No = 4, Name = "Device D", Status = "Error" },
};

[DreamineProperty] private GridRow? _selectedRow;

TimeSpinner — DreamineTimeSpinner

Adjust hours, minutes, seconds with ▲▼ buttons. WPF also supports scroll wheel and keyboard.

:
:

Time: 09:30:00

Show the code behind this Live demo
<div class="dw-timespinner">
    <div>
        <button @onclick="@(() => Vm.Hours++)">▲</button>
        <input type="number" min="0" max="23" @bind="Vm.Hours" />
        <button @onclick="@(() => Vm.Hours--)">▼</button>
    </div>
    <span>:</span>
    <!-- Minutes and seconds use the same structure. -->
</div>
<p>Time: @Vm.TimeDisplay</p>
[DreamineProperty] private int _hours = 9;
[DreamineProperty] private int _minutes = 30;
[DreamineProperty] private int _seconds;

public string TimeDisplay => $"{Hours:D2}:{Minutes:D2}:{Seconds:D2}";

Image — DreamineImage

CornerRadius for rounded corners, ClickCommand for click events. FallbackSource provides a fallback on load failure.

Image clicks 0
Show the code behind this Live demo
<div class="dw-image-demo" @onclick="Vm.ClickImage">
    <svg viewBox="0 0 100 100" width="80" height="80">
        <circle cx="50" cy="50" r="50" fill="#1E90FF"/>
        <circle cx="50" cy="50" r="22" fill="#fff"/>
    </svg>
</div>
<span>Image clicks @Vm.ImageClickCount</span>
[DreamineProperty] private int _imageClickCount;

[DreamineCommand]
private void ClickImage() => ImageClickCount++;