A lightweight infrastructure layer for Avalonia UI applications with modular architecture and dependency injection.
Thanks to the community, Crystal.Avalonia is feature-complete and mature enough for commercial use. We appreciate your support!
- Module System - Organize code into independent, self-contained modules
- Dependency Injection - Built-in support via Microsoft.Extensions.DependencyInjection
- View/ViewModel Wiring - AutoWire, ViewLocator, and lightweight
EventToCommand(default Avalonia xmlns) - AOT Friendly - Trimming and Native AOT support for registered routed event bindings
- Cross-Platform - Works with all Avalonia-supported platforms (Windows, macOS, Linux, Android, iOS, WebAssembly)
Crystal.Avalonia is not an MVVM framework. It does not provide ViewModel base classes or commands. You can use any MVVM library:
- CommunityToolkit.Mvvm
- Prism
- ReactiveUI
- Any other
The library does not include navigation, regions, or an event aggregator.
- 3.0.x — bug fixes only
- 3.1+ — new abstractions (3.1 moves
CrystalOptionsto an instance / DI singleton — see Upgrade from 3.0) - 4.0 — breaking changes
dotnet new install CrystalTemplate::3.1.1dotnet new CT -o MyApp
cd MyApp
dotnet run- Live Demo (WASM)
- 3.1.1 (Current)
- EventToCommand
- Release Notes
- 2.0.1 (Legacy)
- v1.2 (Legacy)
- Upgrade Guide
- Upgrade from 3.0
- Upgrade from 2.0
- Upgrade from v1.2
- API Reference — 3.1.0+
Crystal.Avalonia supports .NET trimming and Native AOT. Registered routed events are supported; the legacy CLR event fallback requires JIT and preserved metadata:
IsAotCompatible=true- The library is annotated for AOT compatibility- Properly annotated
[DynamicallyAccessedMembers]for reflection-heavy operations - No dynamic assembly scanning or runtime type discovery
EventToCommand.EventName resolves registered Avalonia routed events (including inherited
events) through RoutedEventRegistry, without reflecting over *Event fields. Existing
names such as Loaded, Click, and TextChanged work with Native AOT.
For custom or attached routed events, you can also supply the event directly:
<Button EventToCommand.RoutedEvent="{x:Static Button.ClickEvent}"
EventToCommand.Command="{Binding SaveCommand}" />EventBinding.RoutedEvent supports the same syntax inside EventToCommand.Bindings.
An explicit RoutedEvent takes precedence over EventName. Custom event owners must
register their event before resolving it by name; supplying the event directly ensures
the owner is initialized. The legacy CLR EventHandler fallback is available only on
JIT runtimes and requires preserved event metadata in trimmed applications. It is disabled
under Native AOT. Unsupported event names produce an Avalonia warning log.
See AOT Compatibility for more details.
- Fix startup and other routed event commands failing silently after Native AOT publishing.
- Resolve
EventNamethrough Avalonia's event registry instead of reflection over event fields. - Add
EventToCommand.RoutedEventandEventBinding.RoutedEventfor explicit event references. - Log unsupported event bindings and detach subscriptions when binding collections are replaced.
Update the library package with:
dotnet add package Crystal.Avalonia --version 3.1.1Existing routed event XAML remains valid. App-specific DynamicDependency workarounds
for these event fields can be removed after upgrading. CrystalTemplate 3.1.1 generates
applications referencing Crystal.Avalonia 3.1.1. Reinstalling the template affects newly
generated applications; update existing applications' library references separately.
MIT License