From WinUI to Cross-Platform: A Deep Dive into Uno Platform's Architecture Design Philosophy
This post is a structured English summary of a detailed Chinese technical article analyzing Uno Platform's architecture.
Background: WinUI 3's Architecture
The article frames Uno Platform by first examining what it replicates—WinUI 3, the third generation of Microsoft's Windows UI stack:
- Gen 1: WPF (2006) — managed code, DirectX 9, Windows Desktop only.
- Gen 2: UWP XAML (2015) — native C++ core, XAML engine built into the OS, sandboxed UWP apps only.
- Gen 3: WinUI 3 (2020) — native C++ core, decoupled from the OS release cycle via Windows App SDK (shipped as NuGet packages), supports Desktop + UWP app models, DirectX 12 rendering.
- Strategy A (Xamarin.Forms/MAUI): define an abstraction API implemented with native controls per platform. The API is limited to the intersection of all platforms' capabilities.
- Strategy B (Uno Platform): adopt the WinUI 3 API directly and reimplement it for each target (iOS, Android, WebAssembly, Skia desktop). Developers' WinUI skills and code transfer directly.
- Skia rendering (default): the C# Uno.UI framework layer draws the entire UI via Google's Skia 2D engine, with Metal/OpenGL/WebGL hardware backends. Guarantees pixel-identical output across platforms and full Composition API support; no native controls used.
- Native rendering (legacy mode):
UIElementmaps toUIViewsubclasses (iOS),ViewGroupsubclasses (Android), or DOM elements like<div>/<img>(WebAssembly). Provides native input/scrolling behavior, best accessibility, and ability to embed arbitrary native views. - Platform heads: the shared project contains app code plus per-platform entry points under
Platforms/Android,Platforms/iOS,Platforms/WebAssembly,Platforms/Desktop. - Bait-and-switch: at compile time, app code references a type-only "bait" package (
Uno.WinUIreference); at publish time, the real implementation is swapped in—native WinUI 3 (Windows App SDK) on Windows,Uno.WinUI.iOS/Android/WebAssembly/Skiaelsewhere. - Platform-specific code: file-suffix conventions (e.g.,
FilePicker.Android.cs,FilePicker.iOS.cs,FilePicker.Skia.cscompiled only for the matching target) and XAML namespaces likexmlns:android="http://uno.ui/android"andxmlns:ios="http://uno.ui/ios"to embed native views (e.g.,RatingBar,UISwitch) in shared XAML. - Immutable Models (C#
recordtypes) instead of mutable ViewModels; a source generator creates bindable proxies for the View. - Single-direction data flow: the View sends intents to the Model; bindings read generated proxies—easier debugging and testing.
IFeed<T>represents async data streams;IState<T>supports two-way-bound user input state.FeedViewdeclaratively handles loading/error/success states of async operations, replacing hand-managed VisualStates.
WinUI 3 uses a layered architecture:
1. App layer — XAML + C#/C++ business code
2. Framework layer — Microsoft.UI.Xaml.* (controls, data binding, dependency properties, Visual State Manager)
3. Visual layer — Microsoft.UI.Composition (compositor, visual tree, effects, animation); a retained-mode API
4. Graphics layer — DirectX/DirectComposition with GPU acceleration
A core innovation is the dependency property system, which resolves values by precedence: animated value → local value → templated value → style setter → default value. This lets styles, templates, data binding, and animations cooperate seamlessly.
Uno Platform's Core Strategy: API Fidelity, Not Abstraction
Dual Rendering Architecture
Key Innovation: DependencyObject as an Interface + Source Generators
Problem: WinUI UI elements inherit from DependencyObject, but on iOS a Button must inherit UIView and on Android ViewGroup. C# lacks multiple inheritance.
Solution: Uno converts DependencyObject into an interface (IDependencyObject with GetValue/SetValue), and a Roslyn source generator implements the dependency property machinery. Developers annotate properties and the generator emits accessors and DependencyProperty.Register calls at compile time.
XAML Compilation
WinUI compiles XAML to .xbf (XAML Binary Format). Uno instead uses a Roslyn source generator (XamlFileGenerator) to compile MainPage.xaml into C# code—an InitializeComponent() that constructs the element tree, wires events, generates x:Name fields, and compiles x:Bind expressions. Benefits: compile-time type checking, no runtime parsing, and debuggable generated code.
Platform Adaptation
MVUX: A Reactive Alternative to MVVM
Uno introduces MVUX (Model-View-Update-eXtended), adapting Elmish/Redux ideas:
Takeaways
Uno Platform shows that cross-platform UI can be achieved through API fidelity plus code generation rather than abstraction layers: source generators resolve inheritance conflicts, compile XAML to C#, and power reactive patterns—while Skia rendering delivers visual consistency and native mapping preserves platform ergonomics.