StellarUI 1.20.5
dotnet add package StellarUI --version 1.20.5
NuGet\Install-Package StellarUI -Version 1.20.5
<PackageReference Include="StellarUI" Version="1.20.5" />
<PackageVersion Include="StellarUI" Version="1.20.5" />
<PackageReference Include="StellarUI" />
paket add StellarUI --version 1.20.5
#r "nuget: StellarUI, 1.20.5"
#addin nuget:?package=StellarUI&version=1.20.5
#tool nuget:?package=StellarUI&version=1.20.5
StellarUI
A comprehensive cross-platform .NET application framework built on ReactiveUI for creating reactive MVVM applications.
Overview
StellarUI is a reactive UI framework that provides a structured and consistent approach to building applications across different platforms including MAUI, Blazor, and Avalonia. It implements the MVVM (Model-View-ViewModel) pattern and enhances it with reactive programming paradigms, making it easier to manage application state, handle UI events, and implement complex workflows.
The framework is designed to support multiple platforms while maintaining a consistent programming model, allowing developers to share business logic and UI patterns across different .NET UI frameworks.
Key Features
- Cross-platform support: Build applications for MAUI (iOS, Android, Windows, macOS), Blazor (WebAssembly, Server), and Avalonia (Windows, macOS, Linux)
- Reactive programming model: Built on ReactiveUI to provide robust reactive programming paradigms
- Consistent lifecycle management: Standardized lifecycle events (Activated, Deactivated, IsAppearing, IsDisappearing) across all platforms
- Dependency injection: First-class support for registering and resolving services with the
ServiceRegistrationAttribute
- Hot reload support: Enhanced development experience with built-in hot reload capabilities
- View infrastructure: Base classes for all view types with consistent patterns for setup and binding
- Navigation abstractions: Platform-agnostic navigation APIs to simplify cross-platform navigation
- Data binding: Reactive two-way data binding with support for validation
- Popup and modal support: Unified APIs for displaying popups and modals across platforms
Project Structure
StellarUI is composed of several projects, each serving a specific purpose in the framework:
Core Libraries
- Stellar: Core library containing shared interfaces, base classes, and utilities used by all platform implementations
- Stellar.Maui: Implementation for .NET MAUI platform, providing base classes for MAUI UI components
- Stellar.Blazor: Implementation for Blazor WebAssembly and Server, enabling reactive UI for web applications
- Stellar.Avalonia: Implementation for Avalonia UI, supporting desktop applications on Windows, macOS, and Linux
Extensions and Utilities
- Stellar.Maui.PopUp: Extended popup functionality for MAUI applications
- Stellar.FluentValidation: Integration with FluentValidation for input validation across platforms
- Stellar.DiskDataCache: Disk-based caching implementation for persistent storage
Samples
- Stellar.MauiSample: Example application demonstrating MAUI features
- Stellar.BlazorSample: Example application demonstrating Blazor features
- Stellar.AvaloniaSample: Example application demonstrating Avalonia features
- Stellar.MauiBlazorHybridSample: Example application demonstrating hybrid MAUI Blazor approach
Getting Started
Prerequisites
- .NET 6.0 or later
- For MAUI development: .NET MAUI workload installed
- For Blazor development: ASP.NET Core Blazor workload installed
- For Avalonia development: Avalonia UI dependencies
Installation
To use StellarUI in your project, add the relevant package references:
<PackageReference Include="Stellar" Version="latest" />
<PackageReference Include="Stellar.Maui" Version="latest" />
<PackageReference Include="Stellar" Version="latest" />
<PackageReference Include="Stellar.Blazor" Version="latest" />
<PackageReference Include="Stellar" Version="latest" />
<PackageReference Include="Stellar.Avalonia" Version="latest" />
Basic Setup
StellarUI simplifies application setup across all platforms with a focus on minimizing boilerplate code. Just add these two key method calls to your existing app setup:
MAUI Application Setup
// In your MauiProgram.cs
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
// Just add these two lines to enable StellarUI:
.UseStellarComponents<App>() // Register all StellarUI components automatically
.EnableHotReload(); // Enable hot reload capability (optional but recommended)
return builder.Build();
}
Blazor Application Setup
// In your Program.cs
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
// Just add this line to enable StellarUI:
builder.Services.UseStellarComponents<App>(); // Register all StellarUI components automatically
await builder.Build().RunAsync();
Avalonia Application Setup
// In your Program.cs
public static AppBuilder BuildAvaloniaApp() =>
AppBuilder.Configure<App>()
.UsePlatformDetect()
// Just add these two lines to enable StellarUI:
.UseStellarComponents<App>() // Register all StellarUI components automatically
.EnableHotReload() // Enable hot reload capability (optional but recommended)
.UseReactiveUI();
That's it! The UseStellarComponents<App>()
method handles all the necessary registration of services, views, and view models. The framework auto-discovers and registers all classes in your application that have the [ServiceRegistration]
attribute.
Core Concepts
Base Classes and Views
StellarUI provides base classes for each type of view component across platforms:
MAUI Base Classes
ContentPageBase<TViewModel>
: Base class for MAUI ContentPageGridBase<TViewModel>
: Base class for MAUI GridStackLayoutBase<TViewModel>
: Base class for MAUI StackLayoutContentViewBase<TViewModel>
: Base class for MAUI ContentViewShellBase<TViewModel>
: Base class for MAUI ShellPopupPageBase<TViewModel>
: Base class for popup pages
Blazor Base Classes
ComponentBase<TViewModel>
: Base class for Blazor componentsLayoutComponentBase<TViewModel>
: Base class for Blazor layoutsInjectableComponentBase<TViewModel>
: Base class for components with DI
Avalonia Base Classes
WindowBase<TViewModel>
: Base class for Avalonia windowsUserControlBase<TViewModel>
: Base class for Avalonia user controls
View Implementation Pattern
All views follow a consistent pattern for setup and binding:
[ServiceRegistration] // Optional: Register for dependency injection
public class SampleView : ContentViewBase<SampleViewModel>
{
private Label _label;
// Constructor - initialize with the view model
public SampleView(SampleViewModel viewModel)
{
this.InitializeStellarComponent(viewModel);
}
// Setup the UI elements
public override void SetupUserInterface()
{
Content = new Label()
.Assign(out _label);
}
// Bind the UI elements to the view model
public override void Bind(WeakCompositeDisposable disposables)
{
this.OneWayBind(ViewModel, vm => vm.Text, v => v._label.Text)
.DisposeWith(disposables);
// Add other bindings as needed
}
}
ViewModels
ViewModels in StellarUI inherit from ViewModelBase
and use the [Reactive]
attribute from ReactiveUI for reactive properties:
[ServiceRegistration] // Register for dependency injection
public partial class SampleViewModel : ViewModelBase
{
[Reactive]
public string Text { get; set; } = "Hello, World!";
// Initialize method for setup that happens at creation time
protected override void Initialize()
{
// Setup initial values, etc.
}
// Bind method for setting up reactive bindings
protected override void Bind(WeakCompositeDisposable disposables)
{
// Setup observables, commands, etc.
this.WhenAnyValue(x => x.Text)
.Subscribe(text => Console.WriteLine($"Text changed: {text}"))
.DisposeWith(disposables);
}
}
Dependency Injection
StellarUI provides a ServiceRegistrationAttribute
to automatically register classes with the dependency injection system:
// Register as transient (default)
[ServiceRegistration]
public class TransientService : IService { }
// Register as singleton
[ServiceRegistration(Lifetime.Singleton)]
public class SingletonService : IService { }
// Register as scoped
[ServiceRegistration(Lifetime.Scoped)]
public class ScopedService : IService { }
Services can be injected into ViewModels through constructor injection:
[ServiceRegistration]
public partial class SampleViewModel : ViewModelBase
{
private readonly IService _service;
// Constructor injection
public SampleViewModel(IService service)
{
_service = service;
}
// Rest of the ViewModel...
}
Compile-Time Service Registration with Source Generator
StellarUI includes a Roslyn source generator that emits a strongly-typed registration extension based on your assembly, eliminating runtime reflection.
Add the generator package to your project via NuGet:
dotnet add package StellarUI.SourceGenerators --version <latest-version>
Rebuild your project to produce
AddRegisteredServicesFor{YourAssemblyName}.g.cs
inobj/<TFM>/generated
.In your startup code (e.g.,
MauiProgram.cs
orProgram.cs
), call the generated extension:using Stellar; // namespace of generated code builder.Services.AddRegisteredServicesForMyApp(); // replace MyApp with your project's AssemblyName
All [ServiceRegistration]
attributed types will be registered at compile time.
Lifecycle Management
StellarUI provides a consistent set of lifecycle events across all platforms:
- Initialized: Called when the view is first initialized
- Activated: Called when the view is activated
- Deactivated: Called when the view is deactivated
- IsAppearing: Called when the view is appearing on screen
- IsDisappearing: Called when the view is disappearing from screen
- Disposed: Called when the view is being disposed
These events are exposed as IObservable<Unit>
properties on all view base classes, allowing you to react to them with reactive extensions:
public class SampleView : ContentViewBase<SampleViewModel>
{
public SampleView(SampleViewModel viewModel)
{
this.InitializeStellarComponent(viewModel);
// Subscribe to lifecycle events
this.IsAppearing
.Subscribe(_ => Console.WriteLine("View is appearing"))
.DisposeWith(disposables);
this.IsDisappearing
.Subscribe(_ => Console.WriteLine("View is disappearing"))
.DisposeWith(disposables);
}
// Rest of the view...
}
ViewModels can implement the ILifecycleEventAware
interface to be notified of lifecycle events:
[ServiceRegistration]
public partial class SampleViewModel : ViewModelBase, ILifecycleEventAware
{
public void OnLifecycleEvent(LifecycleEvent lifecycleEvent)
{
switch (lifecycleEvent)
{
case LifecycleEvent.IsAppearing:
// Handle appearing
break;
case LifecycleEvent.IsDisappearing:
// Handle disappearing
break;
// Handle other lifecycle events...
}
}
// Rest of the ViewModel...
}
Navigation
StellarUI provides platform-agnostic navigation abstractions to simplify navigation across different platforms:
MAUI Navigation
// Navigate to a page
Observable.Return(Unit.Default)
.NavigateToPage<SimpleSamplePage>(this)
.DisposeWith(disposables);
// Navigate to a page with parameters
Observable.Return(42) // The parameter value
.NavigateToPage<int, ParameterizedPage>(
this,
queryParameters: (value, dict) =>
{
dict.Add("ParameterValue", value);
})
.DisposeWith(disposables);
// Show popup
this.BindCommand(ViewModel, vm => vm.ShowPopupCommand, v => v._popupButton)
.DisposeWith(disposables);
// In ViewModel
_showPopupCommand = ReactiveCommand.CreateFromTask(async () =>
{
await PopupNavigation.Instance.PushAsync(
new SamplePopupPage(new SampleViewModel()));
});
Blazor Navigation
// Navigate in a Blazor component
Navigation.NavigateTo("/details/42");
// In the target page class, receive the parameter
[Parameter]
public string Id { get; set; }
// Or with query parameters
[QueryParameter]
public int ParameterValue { get; set; }
Avalonia Navigation
// Navigate in an Avalonia application
var window = new DetailWindow(new DetailViewModel());
window.Show();
Advanced Features
Validation
StellarUI integrates with FluentValidation for model validation across all platforms:
// Define a validator
public class UserValidator : AbstractValidator<UserViewModel>
{
public UserValidator()
{
RuleFor(x => x.Username).NotEmpty().MinimumLength(4);
RuleFor(x => x.Email).NotEmpty().EmailAddress();
RuleFor(x => x.Age).GreaterThan(0).LessThan(120);
}
}
// Use the validator in a view model
[ServiceRegistration]
public partial class UserViewModel : ViewModelBase, IProvideValidation
{
[Reactive]
public string Username { get; set; }
[Reactive]
public string Email { get; set; }
[Reactive]
public int Age { get; set; }
// Implementation of IProvideValidation
public IEnumerable<ValidationResult> Validate()
{
var validator = new UserValidator();
var results = validator.Validate(this);
return results.Errors
.Select(x => new ValidationResult(x.PropertyName, x.ErrorMessage));
}
// Track validity in the view model
[Reactive]
public bool IsValid { get; private set; }
protected override void Bind(CompositeDisposable disposables)
{
this.WhenAnyValue(x => x.Username, x => x.Email, x => x.Age)
.Throttle(TimeSpan.FromMilliseconds(300))
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ =>
{
IsValid = !Validate().Any();
})
.DisposeWith(disposables);
}
}
Data Caching
The Stellar.DiskDataCache
package provides disk-based caching capabilities:
// Register the cache in your DI setup
services.AddSingleton<IDataCache, DiskCache>();
// Use the cache in a view model
[ServiceRegistration]
public partial class CachedDataViewModel : ViewModelBase
{
private readonly IDataCache _cache;
public CachedDataViewModel(IDataCache cache)
{
_cache = cache;
}
[Reactive]
public ObservableCollection<string> Items { get; private set; }
protected override async void Initialize()
{
// Try to load from cache first
var cachedItems = await _cache.GetAsync<List<string>>("items");
if (cachedItems != null)
{
Items = new ObservableCollection<string>(cachedItems);
}
else
{
Items = new ObservableCollection<string>();
}
}
public async Task SaveItems()
{
await _cache.SetAsync("items", Items.ToList());
}
}
Hot Reload
StellarUI has built-in support for hot reload during development:
// Enable hot reload in a MAUI app
builder.EnableHotReload();
// Enable hot reload in an Avalonia app
AppBuilder.Configure<App>()
// ... other configuration ...
.EnableHotReload()
.UseReactiveUI();
Contributing
Contributions to StellarUI are welcome! Here's how you can contribute:
- Fork the repository
- Create a feature branch:
git checkout -b feature/my-new-feature
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin feature/my-new-feature
- Submit a pull request
Development Setup
- Clone the repository
- Open
Stellar.sln
in Visual Studio or your preferred IDE - Build the solution
- Run one of the sample applications to test your changes
License
StellarUI is licensed under the MIT License. See the LICENSE file for details.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. |
-
net9.0
- Microsoft.Extensions.DependencyInjection (>= 9.0.0)
- ReactiveUI (>= 20.1.63)
NuGet packages (5)
Showing the top 5 NuGet packages that depend on StellarUI:
Package | Downloads |
---|---|
StellarUI.Maui
This is the core MVVM Framework components used by Eight-Bot for building apps. A highly opinionated ReactiveUI on Rails. |
|
StellarUI.FluentValidation
This is the core MVVM Framework components used by Eight-Bot for building apps. A highly opinionated ReactiveUI on Rails. |
|
StellarUI.Avalonia
This is the core MVVM Framework components used by Eight-Bot for building apps. A highly opinionated ReactiveUI on Rails. |
|
StellarUI.Blazor
This is the core MVVM Framework components used by Eight-Bot for building apps. A highly opinionated ReactiveUI on Rails. |
|
StellarUI.DiskDataCache
This is the core MVVM Framework components used by Eight-Bot for building apps. A highly opinionated ReactiveUI on Rails. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.20.5 | 102 | 4/25/2025 |
1.20.4 | 116 | 4/18/2025 |
1.20.3 | 145 | 4/18/2025 |
1.19.1 | 188 | 4/17/2025 |
1.18.2 | 455 | 3/19/2025 |
1.18.1 | 153 | 3/19/2025 |
1.17.4 | 92 | 3/14/2025 |
1.17.3 | 238 | 3/9/2025 |
1.17.2 | 127 | 3/8/2025 |
1.17.1 | 123 | 3/8/2025 |
1.16.5 | 221 | 1/31/2025 |
1.16.3 | 227 | 1/22/2025 |
1.16.2 | 98 | 1/22/2025 |
1.16.1 | 121 | 1/16/2025 |
1.15.4 | 80 | 1/15/2025 |
1.15.3 | 79 | 1/15/2025 |
1.15.2 | 122 | 1/7/2025 |
1.15.1 | 89 | 12/30/2024 |
1.14.3 | 99 | 12/22/2024 |
1.14.2 | 92 | 12/21/2024 |
1.14.1 | 76 | 12/21/2024 |
1.13.2 | 147 | 11/22/2024 |
1.12.3 | 125 | 10/23/2024 |
1.12.2 | 122 | 10/23/2024 |
1.12.1 | 132 | 10/23/2024 |
1.11.5 | 131 | 10/9/2024 |
1.11.4 | 84 | 10/9/2024 |
1.11.3 | 130 | 10/9/2024 |