A 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
PlusUi is in production use — it is not an experiment still looking for its first real workload.
Development is currently strongly demand-driven: things get built when a real application needs them. That keeps the framework focused and free of speculative API, but it also means the gaps sit wherever nobody has happened to need something yet.
So if you run into a missing feature, an awkward API, or something that simply isn't there — please open an issue and tell us. That is by far the fastest route onto the roadmap, and it is genuinely wanted input rather than a nuisance: a reported need is exactly what turns into the next feature. New users are very welcome.
Legend:
- ✅ Stable: Fully tested and production-ready
- 🚧 In Development: Currently being developed, not yet feature-complete
⚠️ Untested: Feature-complete but not fully validated across all scenarios
Core Library: (Required by all platforms)
- .NET 9.0 SDK
- Windows: Windows 11 or later
- Android: Android 8.0 (API 26) or later
- iOS: iOS 11 or later
- Linux/Mac: No specific version requirements
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.h264Create a simple counter application:
App.cs
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(IPlusUiAppBuilder 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 testFor 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.
- Layouts:
VStack,HStack,Grid,ScrollView,Border - Controls:
Label,Button,Entry,Checkbox,Image - Custom Drawing:
Solid,UserControl,RawUserControl - Lists:
ItemsListfor dynamic, data-bound lists
- Solid colors, linear gradients, radial gradients, multi-stop gradients
- Corner radius, borders (solid, dashed, dotted)
- Shadows with customizable blur and offset
- Custom fonts with
FontRegistryService - Theme support with
IApplicationStyle
- Two-way MVVM binding
- Property change notifications
- Command binding with parameters
- Uses CommunityToolkit.Mvvm
- Page-based navigation with
INavigationService - Modal popups with
IPopupService - Configurable popup behavior (background click, escape key)
- Mouse and touch input
- Keyboard support with customizable handlers
- Scroll gestures
- Local images (embedded resources)
- Web images (async loading with caching)
- Custom fonts
The 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.
- Video Output: Renders UI to MP4 files with configurable resolution, frame rate, and duration
- Audio Support: Synchronize audio tracks with your UI animations using
AudioDefinition - Animation System: Built-in animation support for smooth transitions
- FFmpeg Integration: Includes FFmpeg binaries for Windows, macOS, and Linux
- Progress Tracking: Real-time rendering progress with Spectre.Console
VideoApp.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
);
}
}- Promotional Videos: Create product demos and marketing materials
- Tutorials: Generate step-by-step tutorial videos
- Automated Testing: Record UI test runs
- Documentation: Visual documentation of UI features
- Social Media: Export UI animations for social media posts
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:
- GridControl Enhancement: Advanced grid capabilities with sorting and filtering
- dotnet new Templates: Quick project scaffolding with
dotnet new plusui - Rendering Optimization: Internal rendering engine improvements for better performance
- Additional UI controls (DatePicker, Slider, ProgressBar)
- Animation framework
- Accessibility improvements
- Hot reload enhancements
Want 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:
- Measures its desired size based on content and constraints
- Arranges itself and its children within an allocated space
- Supports flexible layouts with alignment, margins, and padding
-
Platform Abstraction: Platform-specific hosts (Desktop, iOS, Android) provide:
- Window/View creation and management
- Input event handling (mouse, touch, keyboard)
- Integration with SkiaSharp's rendering context
- Base Elements: All UI components inherit from
UiElementorUiLayoutElement - Pages: Top-level containers inherit from
UiPageElement - Data Binding: Property change notifications integrated with MVVM pattern
- Fluent API: Method chaining with
.Set*()methods for readable UI construction
This 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:
- Open an issue first to discuss significant changes
- For bug fixes: first commit with failing tests, then the fix
- Follow the project's coding standards (see
CLAUDE.md) - Keep PRs focused and manageable
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.




