SolidAvalonia 0.1.0
dotnet add package SolidAvalonia --version 0.1.0
NuGet\Install-Package SolidAvalonia -Version 0.1.0
<PackageReference Include="SolidAvalonia" Version="0.1.0" />
<PackageVersion Include="SolidAvalonia" Version="0.1.0" />
<PackageReference Include="SolidAvalonia" />
paket add SolidAvalonia --version 0.1.0
#r "nuget: SolidAvalonia, 0.1.0"
#:package SolidAvalonia@0.1.0
#addin nuget:?package=SolidAvalonia&version=0.1.0
#tool nuget:?package=SolidAvalonia&version=0.1.0
SolidAvalonia
A library for building reactive Avalonia UI applications using the SolidJS programming model. SolidAvalonia brings the elegance and simplicity of SolidJS reactive patterns to Avalonia UI development.
SolidAvalonia is built on top of Avalonia.Markup.Declarative, which means all existing classes and extension methods from that library are available for use. For reactive components, signals should be accessed inside the Reactive() method and using the extension methods provided for markup classes.
Features
- Reactive primitives: Signals, memos, and effects inspired by SolidJS
- Automatic dependency tracking: Components automatically update when their dependencies change
- Simple component model: Extend
Componentto create reactive components - Declarative layout helpers: Build UIs with expressive extension methods
- No XAML required: Pure C# approach to building Avalonia applications
- R3 integration: Seamless integration with R3 for advanced reactive patterns and event handling
- Throttling support: Built-in throttling for UI events to optimize performance
Installation
# Install the base library that SolidAvalonia extends
dotnet add package Avalonia.Markup.Declarative
# Add SolidAvalonia from NuGet when published
To use R3 for reactive programming and throttling features:
dotnet add package R3
Getting Started
- Create a new Avalonia application
- Add the SolidAvalonia library
- Create a new control by extending
Component
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Markup.Declarative;
using SolidAvalonia;
using static SolidAvalonia.Solid;
namespace MyApp;
public class MyComponent : Component
{
protected override object Build()
{
// Create signals
var (count, setCount) = CreateSignal(0);
// Create derived state
var doubled = CreateMemo(() => count() * 2);
// Create UI with extension methods
return new StackPanel()
.Spacing(20)
.Children(
// Reactive components automatically update when dependencies change
Reactive(() => new TextBlock()
.Text(() => $"Count: {count()}, Doubled: {doubled()}")
),
new Button()
.Content("+")
.OnClick(_ => setCount(count() + 1))
);
// Create effects for side effects
CreateEffect(() => {
Console.WriteLine($"Count changed: {count()}");
});
}
}
Core Concepts
Signals
Signals are the reactive primitives that store state:
var (count, setCount) = CreateSignal(0);
Console.WriteLine(count()); // Get value: 0
setCount(1); // Set value to 1
Memos
Memos create derived state that updates automatically:
var doubled = CreateMemo(() => count() * 2);
// doubled() updates automatically when count changes
Effects
Effects run side effects when dependencies change:
CreateEffect(() => {
Console.WriteLine($"Count is now: {count()}");
});
Reactive Components
Create UI components that automatically update when their dependencies change:
Reactive(() => new TextBlock()
.Text(() => $"Count: {count()}")
.Foreground(() => count() > 0 ? Brushes.Green : Brushes.Red)
);
Reactive Extensions
SolidAvalonia provides extension methods for common reactive UI patterns:
Text
The Text extension method allows you to reactively bind a function to a TextBlock's text:
using Avalonia.Controls;
using SolidAvalonia.Extensions;
using SolidAvalonia.ReactiveSystem;
// ...
new TextBlock()
.Text(rs, () => $"Count: {count()}")
ShowWhen
The ShowWhen extension method conditionally shows or hides a control based on a reactive expression:
using Avalonia.Controls;
using SolidAvalonia.Extensions;
using SolidAvalonia.ReactiveSystem;
// ...
new Button()
.Content("Reset")
.ShowWhen(rs, () => count() > 0)
Layout Helpers
SolidAvalonia leverages Avalonia.Markup.Declarative to build UIs with chainable extensions. All extension methods from Avalonia.Markup.Declarative are available:
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Markup.Declarative;
// ...
Content = new Border()
.CornerRadius(10)
.Padding(25)
.Child(
new StackPanel()
.Spacing(10)
.Children(
new TextBlock()
.Text("Hello World")
.FontSize(20),
new StackPanel()
.Orientation(Orientation.Horizontal)
.Spacing(5)
.Children(
new Button().Content("Cancel"),
new Button().Content("OK")
)
)
);
When you need to access signals or reactive state within your Avalonia.Markup.Declarative classes, wrap the components in a Reactive() call:
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Markup.Declarative;
using SolidAvalonia;
using SolidAvalonia.Extensions;
// ...
Content = new Border()
.CornerRadius(10)
.Padding(25)
.Child(
new StackPanel()
.Spacing(10)
.Children(
// Static content uses normal Avalonia.Markup.Declarative extensions
new TextBlock()
.Text("Counter App")
.FontSize(20),
// Reactive content that depends on signals
Reactive(() => new TextBlock()
.Text(() => $"Count: {count()}")
.Foreground(() => count() > 0 ? Brushes.Green : Brushes.Red)
),
// Buttons with event handlers
new Button()
.Content("+")
.OnClick(_ => setCount(count() + 1))
)
);
Throttling Events with R3
Optimize UI performance with event throttling using R3:
using System;
using Avalonia.Controls;
using R3;
using SolidAvalonia;
// ...
// Create a subject for button clicks
var clickSubject = new Subject<int>();
// Throttle the clicks using R3's ThrottleFirst operator
clickSubject
.ThrottleFirst(TimeSpan.FromMilliseconds(500))
.Subscribe(v => setCount(count() + v));
// Use in button click handlers
new Button()
.Content("+")
.OnClick(_ => { clickSubject.OnNext(step()); })
Example Applications
See the /examples directory for sample applications:
- Counter: A comprehensive example collection demonstrating:
- Class-based components with inheritance
- Functional components with pure functions
- Component composition with shared signals
- Dynamic theming and styling
- List rendering with For.Each
- Conditional rendering with Show.When
- Throttling for performance optimization
Contributing
Contributions are welcome! Feel free to submit issues or pull requests.
License
MIT License
Publishing
Use the helper script to build, pack, and publish to NuGet:
# 1) Export your NuGet API key (or pass via --api-key)
export NUGET_API_KEY=your_nuget_org_api_key
# 2) Build + pack + publish (default to nuget.org)
scripts/publish-nuget.sh --version 0.1.0
# Build/pack without publishing
scripts/publish-nuget.sh --version 0.1.0 --no-push
# Dry-run (show commands only)
scripts/publish-nuget.sh --version 0.1.0 --dry-run
Options:
--versionoverrides the package version (or read fromSolidAvalonia.csprojif present).--api-keysets the API key (or useNUGET_API_KEY).--sourcesets the NuGet source (defaults tohttps://api.nuget.org/v3/index.json).--no-pushto only build and pack.--dry-runto print commands without executing.
Notes:
- The script passes common NuGet metadata via MSBuild properties (license=MIT, readme=README.md). You can define these in
SolidAvalonia.csprojto override. - Output packages are written to
artifacts/nuget/.
| 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. 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. |
-
net9.0
- Avalonia (>= 11.3.2)
- Avalonia.Markup.Declarative (>= 11.1.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0 | 244 | 10/24/2025 |