WinUI 3 and Windows App SDK
Trigger On
- building native modern Windows desktop UI on WinUI 3
- integrating Windows App SDK features into a .NET app
- deciding between WinUI, WPF, WinForms, and MAUI for Windows work
- implementing MVVM patterns in Windows App SDK applications
Workflow
- Confirm WinUI is the right choice — use when modern Windows-native UI, Fluent Design, and Windows App SDK capabilities are needed. For cross-platform, consider MAUI instead.
- Choose packaging model early — packaged (MSIX) vs unpackaged differ materially for deployment, identity, and API access:
<!-- Unpackaged: add to .csproj -->
<WindowsPackageType>None</WindowsPackageType>
- Apply MVVM pattern with the MVVM Toolkit — keep views dumb, logic in ViewModels:
public partial class ProductsViewModel : ObservableObject
{
[ObservableProperty]
private ObservableCollection<Product> _products = [];
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(DeleteCommand))]
private Product? _selectedProduct;
[RelayCommand(CanExecute = nameof(CanDelete))]
private async Task DeleteAsync()
{
if (SelectedProduct is null) return;
await _productService.DeleteAsync(SelectedProduct.Id);
Products.Remove(SelectedProduct);
}
private bool CanDelete() => SelectedProduct is not null;
}
- Use x:Bind for compiled bindings — better performance and compile-time checking than
{Binding}:
<TextBlock Text="{x:Bind ViewModel.Title, Mode=OneWay}"/>
- Wire DI through
Host.CreateDefaultBuilder — register services, ViewModels, and views. Resolve via App.GetService<T>().
- Implement navigation service — map ViewModels to Pages by convention. See references/patterns.md for the full pattern.
- Handle Windows App SDK features — windowing (AppWindow), custom title bar, app lifecycle, notifications.
- Always set
XamlRoot when showing ContentDialog — omitting this causes silent failures.
- Validate on Windows targets — behavior depends on runtime, packaging model, and Windows version.
Current Upstream Notes
- Windows App SDK
2.3.1 adds schema-constrained Phi Silica JSON output, XamlOptionalChanges, ARM64EC support for Windows ML, Video Super Resolution improvements, and opt-in XAML startup/style/resource-lookup optimizations.
- Windows App SDK
1.8.11 is the current 1.8 servicing patch. It restores focus after storage pickers, fixes MRT fallback resolution, and isolates runtime base-directory environment state; retest picker return focus, resource fallback, and side-by-side runtime activation when maintaining the 1.8 line.
- For unpackaged apps, prefer
ApplicationData.GetForUnpackaged() over registry or custom folder conventions when the app needs first-class app data storage.
- When upgrading to 2.3.1, retest unpackaged
LocalSettings, background tasks, side-placement flyouts, MediaPlayerPresenter device loss, popup pointer replay, ItemsRepeater layouts, Windows ML, and any opted-in XAML change IDs.
flowchart LR
A["Choose WinUI"] --> B["Select packaging model"]
B --> C["MVVM + DI setup"]
C --> D["Navigation and views"]
D --> E["Windows App SDK features"]
E --> F["Validate on target runtime"]
Key Decisions
| Decision |
Guidance |
| Packaged vs unpackaged |
Packaged (MSIX) for Store, auto-update, and full API access; unpackaged for simpler deployment |
| x:Bind vs Binding |
Always prefer x:Bind — compiled, faster, type-safe |
| MVVM Toolkit attributes |
Use [ObservableProperty], [RelayCommand] to eliminate boilerplate |
| Navigation |
Convention-based ViewModel→Page mapping via navigation service |
| Theming |
Use RequestedTheme on root element; respect system theme by default |
Deliver
- modern Windows UI code with clear platform boundaries
- explicit deployment and packaging assumptions
- MVVM pattern with testable ViewModels
- cleaner interop between shared and Windows-specific layers
Validate
- WinUI is chosen for a real product reason, not defaulted to
- Windows App SDK dependencies are explicit in the project file
- packaging and runtime assumptions are tested on target
- x:Bind is used for compiled bindings throughout
- navigation and ContentDialog both work with correct XamlRoot
- custom title bar renders correctly on Windows 10 and 11
References