NXUI.Desktop
12.0.0
dotnet add package NXUI.Desktop --version 12.0.0
NuGet\Install-Package NXUI.Desktop -Version 12.0.0
<PackageReference Include="NXUI.Desktop" Version="12.0.0" />
<PackageVersion Include="NXUI.Desktop" Version="12.0.0" />
<PackageReference Include="NXUI.Desktop" />
paket add NXUI.Desktop --version 12.0.0
#r "nuget: NXUI.Desktop, 12.0.0"
#:package NXUI.Desktop@12.0.0
#addin nuget:?package=NXUI.Desktop&version=12.0.0
#tool nuget:?package=NXUI.Desktop&version=12.0.0
NXUI (next-gen UI)
Creating minimal Avalonia next generation (NXUI, next-gen UI) application using C# 10 and .NET 8
https://user-images.githubusercontent.com/2297442/132313187-32f18c4b-e894-46db-9a9d-9de02f30835e.mp4
Requisites
NXUI
<PackageReference Include="NXUI" Version="12.0.0" />
Additionally, depending on the application type:
Desktop
For Desktop extensions:
<PackageReference Include="NXUI.Desktop" Version="12.0.0" />
or using plain Avalonia:
<PackageReference Include="Avalonia.Desktop" Version="12.0.0" />
Browser
<PackageReference Include="Avalonia.Browser" Version="12.0.0" />
dotnet workload install wasm-tools
Usage
NXUI builders now capture the full UI tree so hot reload can diff it. Return the builder
from your entry point and run the app through HotReloadHost.Run (shipped with
NXUI.Desktop) so NXUI can attach the component and reconcile live updates:
object Build() =>
Window()
.Title("NXUI")
.Content(Label().Content("NXUI"));
return HotReloadHost.Run(Build, "NXUI", args);
var count = 0;
object Build()
=> Window(out var window)
.Title("NXUI").Width(400).Height(300)
.Content(
StackPanel()
.Children(
Button(out var button)
.Content("Welcome to Avalonia, please click me!"),
TextBox(out var tb1)
.Text("NXUI"),
TextBox()
.Text(window.BindTitle()),
Label()
.Content(button.ObserveOnClick().Select(_ => ++count).Select(x => $"You clicked {x} times."))))
.Title(tb1.ObserveText().Select(x => x?.ToUpper()));
return HotReloadHost.Run(Build, "NXUI", args);
HotReloadHost automatically falls back to materializing the window when hot reload is
disabled, so the same entry point works for Release builds without extra flags.
Running without Hot Reload
If you need to pass a concrete window to Avalonia (for example when integrating into a
custom lifetime), call .Mount() on the builder before returning it:
Window Build()
=> Window()
.Title("NXUI")
.Content(Label().Content("NXUI"))
.Mount();
AppBuilder.Configure<Application>()
.UsePlatformDetect()
.UseFluentTheme()
.StartWithClassicDesktopLifetime(Build, args);
Minimalistic Desktop app:
return HotReloadHost.Run(
() => Window().Content(Label().Content("NXUI")),
"NXUI",
args,
ThemeVariant.Dark);
Generate
C#
cd src/Generator
dotnet run -- ../NXUI/Generated
F#
cd src/Generator
dotnet run -- ../NXUI.FSharp/Generated -fsharp
dotnet run app.cs
Using .NET 10 you can run GUI apps using scripts: https://devblogs.microsoft.com/dotnet/announcing-dotnet-run-app/#using-shebang-lines-for-shell-scripts
Note: You might need to adjust shebang line to #!/usr/bin/dotnet run
App.cs
#!/usr/local/share/dotnet/dotnet run
#:package NXUI.Desktop@12.0.0
using Avalonia.Controls;
using Avalonia.Styling;
using NXUI.HotReload;
using static NXUI.Builders;
return HotReloadHost.Run(
() => Window().Content(Label().Content("NXUI")),
"NXUI",
args,
ThemeVariant.Dark,
ShutdownMode.OnLastWindowClose);
chmod +x App.cs
./App.cs
More complex app:
#!/usr/local/share/dotnet/dotnet run
#:package NXUI.Desktop@12.0.0
using NXUI.HotReload;
using static NXUI.Builders;
var count = 0;
object Build()
=> Window(out var window)
.Title("NXUI").Width(400).Height(300)
.Content(
StackPanel()
.Children(
Button(out var button)
.Content("Welcome to Avalonia, please click me!"),
TextBox(out var tb1)
.Text("NXUI"),
TextBox()
.Text(window.BindTitle()),
Label()
.Content(button.ObserveOnClick().Select(_ => ++count).Select(x => $"You clicked {x} times."))))
.Title(tb1.ObserveText().Select(x => x?.ToUpper()));
return HotReloadHost.Run(Build, "NXUI", args);
F# Support
From F# 9.0 and above the compiler resolves extension methods instead of instrinsic properties so, there's no need for a separate F# package or any additional changes to your project files.
Extension methods provided by the main package NXUI
open Avalonia
open Avalonia.Controls
open NXUI.Extensions
open NXUI.HotReload
open type NXUI.Builders
let Build () : obj =
let mutable count = 0
let mutable window = Unchecked.defaultof<Window>
let mutable button = Unchecked.defaultof<Button>
let mutable tb1 = Unchecked.defaultof<TextBox>
Window(window)
.Title("NXUI")
.Width(400)
.Height(300)
.Content(
StackPanel()
.Children(
Button(button).Content("Welcome to Avalonia, please click me!"),
TextBox(tb1).Text("NXUI"),
TextBox().Text(window.BindTitle()),
Label()
.Content(
button.ObserveOnClick()
|> Observable.map (fun _ ->
count <- count + 1
count)
|> Observable.map (fun x -> $"You clicked {x} times.")
|> _.ToBinding()
)
)
)
.Title(tb1.ObserveText())
|> box
[<EntryPoint>]
let Main argv = HotReloadHost.Run(Build, "NXUI", argv)
F# 8.0 Support
The compiler feature is available in the .NET9 SDK and above so even if you target a lower dotnet version you don't need to change your project files.
However, if you must to use the .NET10 SDK explicitly you only need to set the language version to preview In your *.fsproj project and you'll get the same benefits.
<PropertyGroup> <TargetFramework>net10.0</TargetFramework> <LangVersion>preview</LangVersion> </PropertyGroup>
Extensions
NXUI ships with a rich set of extension methods and builder helpers so that all UI composition can be expressed in C#. The code generator produces most of these members for every Avalonia control and property.
Builders
NXUI.Builders exposes factory methods for every control type. Each method
creates the control instance and overloads let you capture it via out var for
later use.
Property helpers
For each Avalonia property the following methods are generated:
<Name>(value)– set the property value.<Name>(IBinding, mode, priority)– bind with an Avalonia binding.<Name>(IObservable<T>, mode, priority)– bind from an observable.Bind<Name>(mode, priority)– create a binding descriptor.Observe<Name>()– observable of property values.On<Name>(handler)– pass the observable to a handler.ObserveBinding<Name>()– observe binding values including errors.OnBinding<Name>(handler)– receive the binding observable.Observe<Name>Changed()– observe full change events.On<Name>Changed(handler)– handler for change observable.
Enum properties get convenience methods for each enum value, e.g.
HorizontalAlignmentCenter().
Event helpers
For routed and CLR events:
ObserveOn<EventName>(routes)– returns anIObservablesequence.On<EventName>(handler, routes)– handler receiving the observable.On<EventName>Handler(action, routes)– attach a simple callback.
Style setters
Set<ClassName><PropertyName> methods on Style and KeyFrame let you define
style values using constants, bindings or observables.
Core runtime helpers
NXUI.Extensions.AvaloniaObjectExtensions provides BindOneWay and
BindTwoWay to link properties or observables without verbose binding code.
NXUI.Extensions.ReactiveObservableExtensions adds utilities for reactive
workflows:
ObserveOnUiThread/SubscribeOnUiThreadTakeUntilDetachedFromVisualTree/SubscribeUntilDetachedDisposeWithDataTemplate<T>WhenAnyValue(single or multiple expressions)
Together these extensions enable complex, reactive UIs built entirely in code while managing resources with minimal overhead.
Hot Reload
Using NXUI Hot Reload
Hot reload is always on – every NXUI project now emits builder-based controls and ships the hot reload runtime by default. No MSBuild properties or preprocessor symbols are required.
Run through the host – wrap your entry point with
HotReloadHost.Runso NXUI can register the component and reconcile live instances:using NXUI.HotReload; object Build() => Window() .Title("NXUI Hot Reload") .Content(Label().Content("Edit a file and save to trigger hot reload.")); return HotReloadHost.Run(Build, "SampleApp", args);Use
dotnet watchor IDE hot reload – the runtime listens for metadata updates and callsNodeRenderer.Reconcilewith the previous node snapshot. The window stays mounted and control state (e.g.,TextBox.Text) survives.Turn on diagnostics when needed – set
NXUI_HOTRELOAD_DIAGNOSTICS=1to see per-reconciliation summaries, including counts for property sets, child add/remove/move operations, and replacements.Implicit boundaries (optional) – set
<EnableNXUIHotReloadBoundaries>true</EnableNXUIHotReloadBoundaries>to weave[HotReloadBoundary]onto controls listed inbuild/HotReloadBoundaries.json. Samples do this automatically for Debug builds viasamples/Directory.Build.props. Usedotnet run --project src/NXUI.Cli -- hotreload boundaries --manifest build/HotReloadBoundaries.json --assembly path/to/MyApp.dllto inspect which controls were annotated (manifest hits, explicit attributes, or state-adapter skips). The same Fody pass also injects[assembly: MetadataUpdateHandler(typeof(NXUI.HotReload.HotReloadMetadataUpdateHandler))], so IDE /dotnet watchnotifications reach NXUI without manual attributes.
Troubleshooting
- No updates apply – ensure your builder delegate returns an
ElementNodetree (not.Mount()ed controls) and that it is hosted byHotReloadHost.Run. - State resets on list changes – provide explicit
.Key("stable-id")for repeating builders or wrap complex containers with.HotReloadBoundary()so the diff engine can reason about reuse. Seedocs/hot-reload-best-practices.mdfor patterns. - Bindings/events stop firing – check analyzer warnings (see
NXUI.Analyzers) and confirm you are not instantiating Avalonia controls manually; the builder pipeline must remain in control for hot reload to succeed. - Layout thrash during updates – enable diagnostics to ensure excessive replacements are not happening; large replace counts often mean missing keys or boundaries.
Release Builds
- The hot reload runtime now ships in every build configuration.
NXUI.propsinjects the requiredRuntimeHostConfigurationOptionautomatically so metadata updates flow without extra project tweaks. - When trimming, keep
NXUI.HotReload.*rooted (the shipped linker descriptors already do this) if you want hot reload support in the published app.
Further Reading
docs/hot-reload-architecture.md– end-to-end design.docs/hot-reload-implementation-plan.md– milestone tracking.docs/hot-reload-best-practices.md– guidance forKey()andHotReloadBoundary()usage.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. 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. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Avalonia.Desktop (>= 12.0.0)
- NXUI (>= 12.0.0)
- Tmds.DBus.Protocol (>= 0.92.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on NXUI.Desktop:
| Package | Downloads |
|---|---|
|
MigrondiUI
This is a simple SQL migrations tool Write your Migration SQL apply them or revert them from your database. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 12.0.0 | 118 | 6/24/2026 |
| 11.3.0.1 | 357 | 7/18/2025 |
| 11.3.0 | 527 | 5/29/2025 |
| 11.1.0.1 | 468 | 10/27/2024 |
| 11.1.0 | 269 | 7/22/2024 |
| 11.0.10 | 338 | 5/5/2024 |
| 11.0.0 | 693 | 7/5/2023 |
| 11.0.0-rc1.1 | 272 | 6/3/2023 |
| 11.0.0-preview8 | 268 | 5/10/2023 |