An open API service indexing awesome lists of open source software.

https://github.com/wieslawsoltes/NXUI

NXUI (nex-ui), next-gen UI - Create minimal Avalonia applications using C# 10 and .NET 8
https://github.com/wieslawsoltes/NXUI

avalonia avaloniaui csharp dotnet minimal xaml

Last synced: 15 days ago
JSON representation

NXUI (nex-ui), next-gen UI - Create minimal Avalonia applications using C# 10 and .NET 8

Awesome Lists containing this project

README

          

# NXUI (next-gen UI)

[![NuGet](https://img.shields.io/nuget/v/NXUI.svg)](https://www.nuget.org/packages/NXUI)
[![NuGet](https://img.shields.io/nuget/dt/NXUI.svg)](https://www.nuget.org/packages/NXUI)

Creating minimal [Avalonia](https://avaloniaui.net/) 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

```xml

```

Additionally, depending on the application type:

### Desktop

For Desktop extensions:
```xml

```
or using plain Avalonia:
```xml

```

### Browser

```xml

```

```
dotnet workload install wasm-tools
```

# Usage

```csharp
Window Build() => Window().Content(Label().Content("NXUI"));

AppBuilder.Configure()
.UsePlatformDetect()
.UseFluentTheme()
.StartWithClassicDesktopLifetime(Build, args);
```

```csharp
var count = 0;

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

AppBuilder.Configure()
.UsePlatformDetect()
.UseFluentTheme()
.WithApplicationName("NXUI")
.StartWithClassicDesktopLifetime(Build, args);
```

Minimalistic Desktop app:
```csharp
Run(
() => Window().Content(Label().Content("NXUI")),
"NXUI",
args,
ThemeVariant.Dark);
```

# Generate

C#
```bash
cd src/Generator
dotnet run -- ../NXUI/Generated
```

F#
```bash
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
```csharp
#!/usr/local/share/dotnet/dotnet run
#:package NXUI.Desktop@11.3.0
NXUI.Desktop.NXUI.Run(
() => Window().Content(Label().Content("NXUI")),
"NXUI",
args,
ThemeVariant.Dark,
ShutdownMode.OnLastWindowClose);
```

```bash
chmod +x App.cs
./App.cs
```

![image](https://github.com/user-attachments/assets/33f7f915-13a2-4c45-b9e3-ecd5dfdfd353)

More complex app:

```csharp
#!/usr/local/share/dotnet/dotnet run
#:package NXUI.Desktop@11.3.0

var count = 0;

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

AppBuilder.Configure()
.UsePlatformDetect()
.UseFluentTheme()
.WithApplicationName("NXUI")
.StartWithClassicDesktopLifetime(Build, args);
```

![image](https://github.com/user-attachments/assets/6dfea182-9725-4904-a201-b9c48aea2915)

## F# Support

From F# 9.0 and above the compiler resolves [extension methods instead of instrinsic properties](https://github.com/dotnet/fsharp/pull/16032) 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`

```fsharp
open Avalonia
open Avalonia.Controls

open NXUI.Extensions
open NXUI.Desktop
open type NXUI.Builders

let Build () =
let mutable count = 0
let mutable window = Unchecked.defaultof
let mutable button = Unchecked.defaultof
let mutable tb1 = Unchecked.defaultof

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

[]
let Main argv = NXUI.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 .NET8 SDK you only need to set the language version to preview
> In your \*.fsproj project and you'll get the same benefits.
>
> ```xml
>
> net8.0
> preview
>
> ```

## 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:

* **`(value)`** – set the property value.
* **`(IBinding, mode, priority)`** – bind with an Avalonia binding.
* **`(IObservable, mode, priority)`** – bind from an observable.
* **`Bind(mode, priority)`** – create a binding descriptor.
* **`Observe()`** – observable of property values.
* **`On(handler)`** – pass the observable to a handler.
* **`ObserveBinding()`** – observe binding values including errors.
* **`OnBinding(handler)`** – receive the binding observable.
* **`ObserveChanged()`** – observe full change events.
* **`OnChanged(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(routes)`** – returns an `IObservable` sequence.
* **`On(handler, routes)`** – handler receiving the observable.
* **`OnHandler(action, routes)`** – attach a simple callback.

### Style setters

`Set` 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` / `SubscribeOnUiThread`
- `TakeUntilDetachedFromVisualTree` / `SubscribeUntilDetached`
- `DisposeWith`
- `DataTemplate`
- `WhenAnyValue` (single or multiple expressions)

Together these extensions enable complex, reactive UIs built entirely in code
while managing resources with minimal overhead.