The Desktop PlusUi Package
$ dotnet add package PlusUi.desktopA fully cross-platform UI Framework for .NET, delivering consistent user experiences across iOS, Android, Windows, Mac, and Linux. Built with SkiaSharp as the rendering layer, PlusUi ensures that all platforms look, feel, and behave exactly the same.
Documentation | NuGet Packages
Core Library: (Required by all platforms)
Install the PlusUi packages via NuGet:
# For Desktop applications (Windows, Mac, Linux)
dotnet add package PlusUi.core
dotnet add package PlusUi.desktop
# For Web (Blazor WebAssembly)
dotnet add package PlusUi.core
dotnet add package PlusUi.web
# For iOS
dotnet add package PlusUi.core
dotnet add package PlusUi.ios
# For Android
dotnet add package PlusUi.core
dotnet add package PlusUi.droid
# For Headless (server-side rendering, testing, automation)
dotnet add package PlusUi.core
dotnet add package PlusUi.headless
# For Video Rendering (H264)
dotnet add package PlusUi.core
dotnet add package PlusUi.h264
Create a simple counter application:
App.cs
using Microsoft.Extensions.Hosting;
using PlusUi.core;
namespace MyFirstApp;
public class App : IAppConfiguration
{
public void ConfigureWindow(PlusUiConfiguration config)
{
config.Title = "My First PlusUi App";
config.Size = new SizeI(800, 600);
}
public void ConfigureApp(HostApplicationBuilder builder)
{
// Register your pages
builder.AddPage<MainPage>().WithViewModel<MainPageViewModel>();
}
public UiPageElement GetRootPage(IServiceProvider serviceProvider)
{
return serviceProvider.GetRequiredService<MainPage>();
}
}
MainPage.cs
using PlusUi.core;
using SkiaSharp;
namespace MyFirstApp;
public class MainPage(MainPageViewModel vm) : UiPageElement(vm)
{
protected override UiElement Build()
{
return new VStack(
// Label showing the counter
new Label()
.SetText("Counter App")
.SetTextSize(32)
.SetTextColor(SKColors.White)
.SetHorizontalTextAlignment(HorizontalTextAlignment.Center)
.SetMargin(new Margin(0, 20)),
// Display current count with data binding
new Label()
.BindText(nameof(vm.Count), () => $"Count: {vm.Count}")
.SetTextSize(24)
.SetTextColor(SKColors.LightGray)
.SetHorizontalTextAlignment(HorizontalTextAlignment.Center)
.SetMargin(new Margin(0, 10)),
// Button to increment counter
new Button()
.SetText("Click Me!")
.SetPadding(new Margin(20, 10))
.SetBackground(new SolidColorBackground(SKColors.DodgerBlue))
.SetCornerRadius(8)
.SetCommand(vm.IncrementCommand)
.SetMargin(new Margin(20))
).SetHorizontalAlignment(HorizontalAlignment.Center)
.SetVerticalAlignment(VerticalAlignment.Center);
}
}
MainPageViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace MyFirstApp;
public partial class MainPageViewModel : ObservableObject
{
public int Count
{
get => field;
set => SetProperty(ref field, value);
}
[RelayCommand]
private void Increment()
{
Count++;
}
}
# Build the solution
dotnet build
# Run on Desktop
dotnet run --project YourDesktopProject
# Run tests
dotnet test
For more examples, explore the samples/Sandbox project in this repository.
Unlike frameworks that adapt to native controls, PlusUi renders identically across all platforms through SkiaSharp. What you design is exactly what users see, regardless of device.
Clean, intuitive MVVM binding with a pure C# approach. No XAML to learn, no complex markup languages - just straightforward code that's familiar to .NET developers.
Method chaining makes UI construction readable and maintainable:
new Button()
.SetText("Save")
.SetIcon("save.png")
.SetPadding(new Margin(15, 10))
.SetBackground(new SolidColorBackground(SKColors.ForestGreen))
.SetCornerRadius(8)
.SetCommand(vm.SaveCommand)
By using a consistent rendering approach, PlusUi isn't constrained by platform-specific UI capabilities or limitations.
VStack, HStack, Grid, ScrollView, BorderLabel, Button, Entry, Checkbox, ImageSolid, UserControl, RawUserControlItemsList for dynamic, data-bound listsFontRegistryServiceIApplicationStyleINavigationServiceIPopupServiceThe PlusUi.h264 package provides a unique capability: rendering your PlusUi application directly to an H264 video file. This is perfect for creating animated demos, promotional videos, tutorials, or any scenario where you need to convert your UI into video format.
AudioDefinitionVideoApp.cs
using Microsoft.Extensions.Hosting;
using PlusUi.core;
using PlusUi.h264;
public class VideoApp : IVideoAppConfiguration
{
public void ConfigureVideo(VideoConfiguration config)
{
config.Width = 1920;
config.Height = 1080;
config.OutputFilePath = "output.mp4";
config.FrameRate = 60;
config.Duration = TimeSpan.FromSeconds(10);
}
public void ConfigureApp(HostApplicationBuilder builder)
{
builder.AddPage<MainPage>().WithViewModel<MainPageViewModel>();
builder.StylePlusUi<MyCustomStyle>();
}
public UiPageElement GetRootPage(IServiceProvider serviceProvider)
{
return serviceProvider.GetRequiredService<MainPage>();
}
public IAudioSequenceProvider? GetAudioSequenceProvider(IServiceProvider serviceProvider)
{
// Return null for no audio, or implement IAudioSequenceProvider
return null;
}
}
Program.cs
using PlusUi.h264;
var app = new PlusUiApp(args);
app.CreateApp(builder => new VideoApp());
Implement IAudioSequenceProvider to add synchronized audio:
public class MyAudioProvider : IAudioSequenceProvider
{
public IEnumerable<AudioDefinition> GetAudioSequence()
{
yield return new AudioDefinition(
FilePath: "background-music.mp3",
StartTime: TimeSpan.Zero,
Volume: 0.8f
);
yield return new AudioDefinition(
FilePath: "sound-effect.wav",
StartTime: TimeSpan.FromSeconds(2.5),
Volume: 1.0f
);
}
}
The following example demonstrates how PlusUi code translates into UI. This shows the complete flow from code to visual output:
For more examples and interactive demos, explore the samples/Sandbox project in this repository.
git clone https://github.com/BernhardPollerspoeck/PlusUi.git
cd PlusUi
# Build entire solution
dotnet build PlusUi.sln
# Build with minimal output
dotnet build PlusUi.sln -v q
# Run all tests
dotnet test PlusUi.sln
# Run a specific test
dotnet test PlusUi.sln --filter "FullyQualifiedName~UiPlus.core.Tests.LabelTests"
PlusUi/
├── source/
│ ├── PlusUi.core/ # Core framework (cross-platform)
│ ├── PlusUi.desktop/ # Desktop implementation
│ ├── PlusUi.ios/ # iOS implementation
│ ├── PlusUi.droid/ # Android implementation
│ └── PlusUi.SourceGenerators/ # Code generation tools
├── samples/
│ └── Sandbox/ # Example application
└── tests/
└── UiPlus.core.Tests/ # Unit tests
We're actively working on the following features for upcoming releases:
dotnet new plusuiWant to see something specific? Open an issue and let us know!
PlusUi implements a custom UI framework with a clean separation of concerns:
SkiaSharp Rendering Layer: All rendering is handled by SkiaSharp, providing direct access to the 2D graphics canvas. This ensures consistent visual output across all platforms.
Custom Layout Engine: The framework implements a measurement and arrangement system similar to WPF/MAUI, where every UI element:
Platform Abstraction: Platform-specific hosts (Desktop, iOS, Android) provide:
UiElement or UiLayoutElementUiPageElement.Set*() methods for readable UI constructionThis architecture allows PlusUi to deliver consistent user experiences across platforms while maintaining flexibility and performance.
Join our Discord community to get support, share feedback, or discuss your experiences with PlusUi:
We welcome all contributions! Whether it's fixing a typo, improving documentation, reporting bugs, or implementing new features - every contribution matters and is appreciated.
Please read our Contributing Guide before submitting a pull request. It contains important information about our PR requirements, including our test-first approach that helps ensure changes can be reviewed and merged efficiently.
Quick Overview:
CLAUDE.md)Thank you for helping make PlusUi better!
This project is licensed under the MIT License - see the LICENSE file for details.
The MIT License allows for wide usage and contribution while remaining open and accessible to developers.
After years of working with various cross-platform UI frameworks and encountering inconsistencies between platforms, PlusUi was born from curiosity: what if consistency was the absolute priority? This project represents a journey to create something where what you design is exactly what users see, regardless of device.