Files
wehub-resource-sync a6e8bcde90
Check asset sync / cli/assets must match src/ui-ux-pro-max (push) Failing after 4s
Release / Semantic release (push) Has been skipped
Smoke test data / smoke (push) Failing after 0s
chore: import upstream snapshot with attribution
2026-07-13 11:58:17 +08:00

27 KiB

1NoCategoryGuidelineDescriptionDoDon'tCode GoodCode BadSeverityDocs URL
21XAMLUse WinUI XAML API surfaceUno implements the WinUI API across platformsMicrosoft.UI.Xaml namespace for all UI codeWPF or Xamarin.Forms namespacesusing Microsoft.UI.Xaml.Controls;using System.Windows.Controls; or using Xamarin.Forms;Highhttps://platform.uno/docs/articles/implemented-views.html
32XAMLCheck API implementation statusNot all WinUI APIs are implemented on every platformUno API compatibility docs before using new APIsAssuming all WinUI APIs work everywhereCheck platform.uno/docs for API statusUsing unimplemented API and discovering at runtimeHighhttps://platform.uno/docs/articles/implemented-views.html
43XAMLUse Uno.WinUI not Uno.UI for new projectsUno.WinUI uses WinUI 3 APIsUno.WinUI NuGet packages for new projectsUno.UI (UWP API surface) for new projects<Project Sdk="Uno.Sdk"> (Uno.WinUI / WinUI 3 surface implicit)<PackageReference Include="Uno.UI"/> (legacy UWP API surface)Mediumhttps://platform.uno/docs/articles/updating-to-winui3.html
54XAMLUse XAML Hot ReloadSpeed up development with live XAML editingHot Reload for iterating on layoutsRestarting app for every XAML changeClick Hot Reload button in VS toolbar or save in VS Code/Rider to apply XAML changesFull rebuild for margin tweakMediumhttps://platform.uno/docs/articles/features/working-with-xaml-hot-reload.html
65ConditionalUse platform-specific XAMLConditional namespaces for platform-specific UIxmlns:android xmlns:ios xmlns:wasm for platform XAMLShared XAML when platforms need different controls<TextBlock android:Text="Android" ios:Text="iOS" Text="Default"/>#if in code-behind to set text per platformMediumhttps://platform.uno/docs/articles/platform-specific-xaml.html
76ConditionalUse partial classes for platform codeSeparate platform implementations in partial filesPartial class files with platform-specific logic#if directives in shared code for large blocksMainPage.iOS.cs MainPage.Android.cs partial class files#if __IOS__ ... #elif __ANDROID__ ... 100-line blocks in shared fileMediumhttps://platform.uno/docs/articles/platform-specific-csharp.html
87ConditionalUse preprocessor symbols correctlyTarget correct platforms with defines__IOS__ __ANDROID__ __WASM__ __DESKTOP__ for platform checksInventing custom symbols or checking OS at runtime#if __ANDROID__ Android-specific code #endifif (RuntimeInformation.IsOSPlatform(OSPlatform.Android)) for compile-time choiceMediumhttps://platform.uno/docs/articles/platform-specific-csharp.html
98ConditionalMinimize platform-specific codeKeep shared code maximizedAbstract platform differences behind interfacesDuplicating logic across platform filesIDeviceService with per-platform implementationSame 50 lines copy-pasted into iOS and Android partial classesHighhttps://platform.uno/docs/articles/platform-specific-csharp.html
109NavigationUse Frame-based navigationStandard WinUI navigation patternFrame.Navigate with page typesManual content swappingrootFrame.Navigate(typeof(DetailPage), parameter);contentPresenter.Content = new DetailPage();Mediumhttps://platform.uno/docs/articles/guides/native-frame-nav-tutorial.html
1110NavigationUse Uno.Extensions.NavigationType-safe navigation with DI integrationUno.Extensions navigation for complex appsManual Frame management in large appsnavigator.NavigateViewModelAsync<DetailViewModel>(this, data: item);Frame.Navigate with string parsing everywhereMediumhttps://platform.uno/docs/articles/external/uno.extensions/doc/Overview/Navigation/NavigationOverview.html
1211NavigationHandle platform back navigationSystemNavigationManager.BackRequested works on Android iOS and WASM but is unimplemented on WinAppSDK desktop where calling GetForCurrentView() throws at runtimeSubscribe to BackRequested only on platforms that support it or use Uno.Toolkit NavigationBar for cross-platform back UXCalling SystemNavigationManager.GetForCurrentView() on WinUI 3 desktop without a guard#if __ANDROID__ || __IOS__ || __WASM__ SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested; #endifSystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested; with no platform guard — crashes on Windows desktopHighhttps://platform.uno/docs/articles/guides/native-frame-nav-tutorial.html
1312NavigationUse deep linkingSupport URI activation across platformsHandle protocol activation and URI routingSingle entry point ignoring activationRoute URIs to specific pages on activationIgnoring OnLaunched activation argsMediumhttps://platform.uno/docs/articles/features/protocol-activation.html
1413RenderersUnderstand Skia vs native renderingUno offers both rendering approachesSkia for pixel-perfect cross-platform consistencyAssuming native rendering on all platforms<TargetFrameworks>net10.0-desktop;net10.0-browserwasm</TargetFrameworks> uses unified Skia Desktop shellExpecting platform-native controls on Skia targetsHighhttps://platform.uno/docs/articles/features/using-skia-desktop.html
1514RenderersUse unified net10.0-desktop targetUno 5.2+ ships a single Skia Desktop shell that auto-selects X11 Win32 or AppKit per OS — Skia.Gtk Skia.Linux.Framebuffer and Skia.WPF heads are deprecatednet10.0-desktop TFM with UnoPlatformHostBuilder for cross-platform desktopTargeting the legacy Skia.Gtk or Skia.Linux.Framebuffer heads in new projects<TargetFrameworks>net10.0-desktop</TargetFrameworks> in the Uno.Sdk single projectPer-OS Skia.Gtk Skia.MacOS Skia.Linux.Framebuffer head projectsMediumhttps://platform.uno/docs/articles/features/using-skia-desktop.html
1615RenderersTest rendering on each targetVisual differences exist between renderersVisual testing on each active target platformTesting only on Windows assuming others matchScreenshot tests on iOS Android WASM and DesktopTesting only on Windows DesktopHighhttps://platform.uno/docs/articles/external/uno.uitest/doc/using-uno-uitest.html
1716RenderersUse platform-native features when neededAccess native APIs through Uno abstractionsNative platform APIs via platform-specific codeAvoiding native features for purity#if __IOS__ UIKit API call #endif for camera accessPure shared code that avoids using the cameraMediumhttps://platform.uno/docs/articles/platform-specific-csharp.html
1817PerformanceOptimize WASM bundle sizeWebAssembly downloads can be largeIL linker and AOT for smaller WASM bundlesDefault settings for production WASM<WasmShellILLinkerEnabled>true</WasmShellILLinkerEnabled>Publishing WASM without linkerHighhttps://platform.uno/docs/articles/features/using-il-linker-webassembly.html
1918PerformanceUse x:Load for deferred XAMLDefer element creation until neededx:Load=False for hidden panels and tabsLoading all UI elements upfront<StackPanel x:Load="{x:Bind ShowAdvanced}">Always-loaded Collapsed panelsMediumhttps://platform.uno/docs/articles/features/windows-ui-xaml-xbind.html
2019Data BindingUse x:Bind for compiled bindingsCompiled bindings eliminate runtime reflection — Uno supports x:Bind across iOS Android WASM Skia and Windows targets that compile XAML so prefer it over {Binding} for static well-typed bindingsx:Bind for property and event bindings; reserve {Binding} for runtime-typed DataContext scenarios{Binding} everywhere when x:Bind would compile<TextBlock Text="{x:Bind ViewModel.Title, Mode=OneWay}"/><TextBlock Text="{Binding Title}"/> for a statically known propertyHighhttps://platform.uno/docs/articles/features/windows-ui-xaml-xbind.html
2120PerformanceProfile per platformPerformance characteristics vary by targetPlatform-specific profiling toolsAssuming desktop perf equals mobileInstruments on iOS and Android Profiler on AndroidProfiling only on WindowsMediumhttps://platform.uno/docs/articles/guides/profiling-applications.html
2221StylingUse WinUI theme resourcesConsistent theming across platformsThemeResource for adaptive colorsHardcoded colors per platformBackground="{ThemeResource ApplicationPageBackgroundThemeBrush}"Background="#FFFFFF"Highhttps://platform.uno/docs/articles/features/working-with-themes.html
2323StylingUse Lightweight StylingOverride control sub-properties via resourcesLightweight styling keys for minor tweaksFull ControlTemplate for small changes<Button><Button.Resources><StaticResource x:Key="ButtonBackground" ResourceKey="AccentBrush"/></Button.Resources></Button>Copying entire ControlTemplate to change one colorMediumhttps://platform.uno/docs/articles/external/uno.themes/doc/lightweight-styling.html
2424StylingTest themes on each platformTheme rendering differs across platformsVisual theme testing on all targetsAssuming themes look identical everywhereScreenshot comparison across platforms for themed controlsTheming only tested on WindowsLowhttps://platform.uno/docs/articles/features/working-with-themes.html
2525ArchitectureUse MVVM patternSeparate view and logicCommunityToolkit.Mvvm or Prism for MVVMCode-behind for business logic[ObservableProperty] public partial string Title { get; set; } [RelayCommand] private void Save() { }MainPage.xaml.cs with all logicHighhttps://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/
2626ArchitectureUse Uno.ExtensionsOfficial extension libraries for common patternsUno.Extensions for DI navigation configurationBuilding infrastructure from scratchHost.CreateDefaultBuilder().UseNavigation().UseConfiguration()Manual DI and navigation setupMediumhttps://platform.uno/docs/articles/external/uno.extensions/doc/ExtensionsOverview.html
2727ArchitectureUse dependency injectionRegister services for testabilityMicrosoft.Extensions.DI through Uno.ExtensionsStatic service locators and singletonsservices.AddSingleton<IApiService, ApiService>();ApiService.Instance or new ApiService() in ViewModelsMediumhttps://platform.uno/docs/articles/external/uno.extensions/doc/Learn/DependencyInjection/DependencyInjectionOverview.html
2828ArchitectureShare code via class librariesMaximize code reuse across targetsBusiness logic in .NET Standard or shared libraryBusiness logic in platform head projectsMyApp.Core class library referenced by all headsBusiness logic in MyApp.Wasm.csprojMediumhttps://platform.uno/docs/articles/cross-targeted-libraries.html
2929ArchitectureUse Uno.Resizetizer for assetsSingle source SVG to multi-platform assetsUnoImage for automatic asset generation from SVGManual asset export per resolution and platform<UnoImage Include="Assets/icon.svg" BaseSize="24,24"/>Manually exporting icon_1x.png icon_2x.png icon_3x.png per platformMediumhttps://platform.uno/docs/articles/external/uno.resizetizer/doc/using-uno-resizetizer.html
3030AccessibilitySet AutomationPropertiesEnable screen readers across platformsAutomationProperties.Name on interactive controlsControls without accessible names<Button AutomationProperties.Name="Submit form"><SymbolIcon Symbol="Accept"/></Button><Button><SymbolIcon Symbol="Accept"/></Button> without nameHighhttps://platform.uno/docs/articles/features/working-with-accessibility.html
3131AccessibilityTest accessibility per platformEach platform has different assistive techTest with VoiceOver TalkBack and NarratorTesting accessibility on one platform onlyVoiceOver on iOS + TalkBack on Android + Narrator on WindowsOnly testing with Narrator on WindowsHighhttps://platform.uno/docs/articles/features/working-with-accessibility.html
3232AccessibilitySupport platform text scalingRespect user font size preferencesDynamic font scaling for all textFixed font sizes ignoring accessibilityFontSize="{ThemeResource BodyTextBlockFontSize}"FontSize="14" everywhereMediumhttps://platform.uno/docs/articles/features/working-with-accessibility.html
3333TestingUnit test ViewModelsTest business logic independentlyxUnit or MSTest on shared ViewModel codeUI testing only[Fact] public void LoadData_SetsItems() { vm.Load(); Assert.NotEmpty(vm.Items); }Manual testing on each platformMediumhttps://platform.uno/docs/articles/external/uno.uitest/doc/using-uno-uitest.html
3434TestingUse Uno.UITest for integrationCross-platform UI testing frameworkUno.UITest for automated UI tests across platformsManual regression testingapp.WaitForElement("SaveButton"); app.Tap("SaveButton");Manual click-through on each platformMediumhttps://platform.uno/docs/articles/external/uno.uitest/doc/using-uno-uitest.html
3535WASMShow an extended splash screen on WASMWASM bundle download and runtime startup take several seconds on first load — render branded UI immediately so users do not see a blank page (AOT and trimming are covered separately)Render a splash overlay in wwwroot/index.html that hides on first XAML navigationLetting the user wait on a blank white page while the runtime bootsindex.html: <div id="uno-loading">Loading…</div> hidden via JS interop after first Frame.NavigateNo splash markup in index.html — 5-second blank page on first visitMediumhttps://platform.uno/docs/articles/external/uno.wasm.bootstrap/doc/runtime-execution-modes.html
3636WASMUse AOT compilation for performanceAhead-of-time compilation improves runtime speedAOT for production WASM buildsInterpreter mode in production<WasmShellMonoRuntimeExecutionMode>InterpreterAndAOT</WasmShellMonoRuntimeExecutionMode>Default interpreter mode in production deploymentMediumhttps://platform.uno/docs/articles/external/uno.wasm.bootstrap/doc/runtime-execution-modes.html
3737WASMHandle browser limitationsWASM runs in browser sandboxFeature detection for browser APIsAssuming desktop capabilities in browser[JSImport("globalThis.hasApi")] static partial bool HasApi(); #if __WASM__ if (HasApi()) { ... } #endif#if __WASM__ StorageFile.GetFileFromPathAsync("C:/data") #endifMediumhttps://platform.uno/docs/articles/platform-specific-csharp.html
3838ControlsUse NavigationView for app shellWinUI NavigationView for consistent navigation across platformsNavigationView with MenuItems for app navigationCustom hamburger menu implementation<NavigationView><NavigationView.MenuItems><NavigationViewItem Content="Home" Icon="Home"/></NavigationView.MenuItems></NavigationView>Custom SplitView with manual toggle buttonHighhttps://learn.microsoft.com/en-us/windows/apps/develop/ui/controls/navigationview
3939ControlsUse ContentDialog for modal interactionsCross-platform modal dialogs using WinUI APIContentDialog for confirmations and inputCustom overlay Panel as dialog<ContentDialog Title="Confirm" PrimaryButtonText="OK" CloseButtonText="Cancel"/>Grid overlay with manual focus trappingMediumhttps://learn.microsoft.com/en-us/windows/apps/develop/ui/controls/dialogs-and-flyouts/dialogs
4040ControlsUse CommandBar for app actionsStandard command bar with primary and secondary commandsCommandBar with AppBarButtons for toolbar actionsCustom StackPanel toolbar<CommandBar><AppBarButton Icon="Save" Label="Save"/><AppBarButton Icon="Delete" Label="Delete"/></CommandBar><StackPanel Orientation="Horizontal"><Button>Save</Button></StackPanel>Mediumhttps://learn.microsoft.com/en-us/windows/apps/develop/ui/controls/command-bar
4141ControlsUse ToggleSwitch for boolean settingsPlatform-native toggle control for on/off preferencesToggleSwitch for settings and feature flagsCheckBox for toggle settings<ToggleSwitch Header="Dark Mode" IsOn="{x:Bind ViewModel.IsDarkMode, Mode=TwoWay}"/><CheckBox Content="Enable dark mode"/>Lowhttps://learn.microsoft.com/en-us/windows/apps/develop/ui/controls/toggles
4242Data BindingImplement INotifyPropertyChangedEnable UI updates when ViewModel properties changeCommunityToolkit.Mvvm [ObservableProperty] for auto-notificationProperties without change notification[ObservableProperty] public partial string Title { get; set; }public string Title { get; set; } without notificationHighhttps://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/
4343Data BindingUse ObservableCollection for bound listsCollection change notifications for ItemsSources across platformsObservableCollection<T> for data-bound listsList<T> for bound ItemsSourcesObservableCollection<Item> Items { get; } = new();List<Item> Items { get; set; } = new();Highhttps://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/
4444LifecycleHandle app suspension on mobileiOS and Android may suspend or terminate the app — WinAppSDK desktop does not raise Suspending so use window Closed for desktop save-stateSave state in OnSuspending and restore on activationIgnoring lifecycle losing user state on mobileApplication.Current.Suspending += (s, e) => { var d = e.SuspendingOperation.GetDeferral(); SaveState(); d.Complete(); };No suspend handler losing form data on mobileHighhttps://platform.uno/docs/articles/features/windows-ui-xaml-application.html
4545LifecycleUse Uno.Extensions.Hosting for startupStructured app initialization with DI and configurationIHost builder pattern for app startup and service registrationManual initialization in App constructorHost.CreateDefaultBuilder().ConfigureServices(s => s.AddSingleton<MainViewModel>()).Build();new MainViewModel() in App.xaml.cs constructorMediumhttps://platform.uno/docs/articles/external/uno.extensions/doc/Overview/Hosting/HostingOverview.html
4646PerformanceUse ListView virtualization for large listsOnly renders visible items to reduce memory and layout costListView with default ItemsStackPanel virtualizationItemsControl or StackPanel for large data sets<ListView ItemsSource="{x:Bind Items}"/> (virtualizes by default)<ItemsControl><StackPanel> rendering 5000 items at onceHighhttps://learn.microsoft.com/en-us/windows/apps/develop/ui/controls/listview-and-gridview
4747AccessibilitySupport keyboard navigation on desktopSkia and WinAppSDK targets need full keyboard operability — note TabIndex routing is not fully implemented on every Uno targetAccessKey and KeyboardAccelerator on Skia and WinAppSDK targetsMouse-only interactions on desktop<Button AccessKey="S" Content="Save"><Button.KeyboardAccelerators><KeyboardAccelerator Modifiers="Control" Key="S"/></Button.KeyboardAccelerators></Button>Clickable controls without keyboard support on desktopHighhttps://learn.microsoft.com/en-us/windows/apps/develop/input/keyboard-accelerators
4848WASMUse service workers for offline supportEnable PWA capabilities for WASM deploymentsService worker registration for caching and offline modeOnline-only WASM app with no offline fallback<WasmPWAManifestFile>manifest.webmanifest</WasmPWAManifestFile>No service worker leaving WASM app unusable offlineLowhttps://platform.uno/docs/articles/external/uno.wasm.bootstrap/doc/features-pwa.html
4949PerformanceMarshal to UI thread with DispatcherQueueCross-thread access to UI elements throws — capture the UI DispatcherQueue once and use TryEnqueue to update from background workDispatcherQueue.GetForCurrentThread().TryEnqueue from background workTouching UI controls directly from a Task_dispatcher.TryEnqueue(() => StatusText.Text = "Done");await Task.Run(() => StatusText.Text = "Done"); throws on non-UI threadHighhttps://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.dispatching.dispatcherqueue
5050StylingMerge XamlControlsResources in App.xamlRequired for Fluent control styles to load — without it controls render with no templateAdd XamlControlsResources at the top of Application.Resources MergedDictionariesSkipping the merged dictionary and wondering why Buttons look unstyled<Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/></ResourceDictionary.MergedDictionaries></ResourceDictionary></Application.Resources><Application.Resources><SolidColorBrush x:Key="MyBrush" Color="Red"/></Application.Resources> with no XamlControlsResources mergedHighhttps://platform.uno/docs/articles/features/fluent-styles.html
5151ArchitectureUse async [RelayCommand] for I/OAsyncRelayCommand reports CanExecute=false (raising CanExecuteChanged) and exposes IsRunning while the Task is in flight — the bound control is disabled and re-entrancy is prevented by default (AllowConcurrentExecutions=false)[RelayCommand] on a Task-returning method for awaitable workasync void event handlers calling .Wait() or .Result[RelayCommand] private async Task LoadAsync() { Items = await _api.GetAsync(); }public void OnLoadClick(object s, EventArgs e) { LoadAsync().Wait(); } deadlock riskMediumhttps://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/generators/relaycommand
5252ArchitectureUse x:Uid for localized stringsWinUI x:Uid resolves UI text from .resw resources at runtime — use it instead of hardcoded strings to support localization across iOS Android WASM and desktop from a single projectx:Uid on every user-facing string with matching .resw entries per language under Strings/{lang}/Resources.reswHardcoding language-specific strings into XAML or code-behind<Button x:Uid="SubmitButton"/> with Strings/en/Resources.resw entry SubmitButton.Content=Submit<Button Content="Submit"/> hardcoded in XAMLHighhttps://platform.uno/docs/articles/features/working-with-strings.html
5353ArchitectureWire up ILogger via Uno.Extensions.LoggingCross-platform logging routes to platform-native sinks (OSLog on iOS Console on WASM Debug elsewhere) when configured through the IHost builderInject ILogger<T> into ViewModels and services and call UseLogging() on the host builderConsole.WriteLine or platform-specific log APIs scattered across shared codeHost.CreateDefaultBuilder().UseLogging(c => c.SetMinimumLevel(LogLevel.Information)) and ILogger<MainViewModel> via constructor injectionConsole.WriteLine("error") in shared code with no platform-aware routingMediumhttps://platform.uno/docs/articles/external/uno.extensions/doc/Overview/Logging/LoggingOverview.html
5454PerformanceEnable PublishAot on net10.0-desktopSkia Desktop on .NET 10 supports Native AOT for faster cold start and smaller deployments — opt in per-target so debug builds remain fast<PublishAot>true</PublishAot> in a TFM-conditional PropertyGroup for net10.0-desktop release buildsEnabling PublishAot globally and breaking debug iteration on every TFM<PropertyGroup Condition="'$(TargetFramework)'=='net10.0-desktop' AND '$(Configuration)'=='Release'"><PublishAot>true</PublishAot></PropertyGroup><PublishAot>true</PublishAot> at root with no TFM/Configuration conditionMediumhttps://platform.uno/docs/articles/features/using-skia-desktop.html
5555PerformanceNever block on async with .Result or .Wait()Blocking on a Task from the UI thread deadlocks because the awaiter cannot resume on the captured SynchronizationContext — always await async APIs through to the event handlerAwait async methods all the way up; in libraries call ConfigureAwait(false) to avoid context captureCalling .Result .Wait() or GetAwaiter().GetResult() on a Task from the UI threadprivate async void OnLoadClick(object s, RoutedEventArgs e) { var data = await _api.GetAsync(); Items = data; }private void OnLoadClick(object s, RoutedEventArgs e) { var data = _api.GetAsync().Result; } // deadlocks on UI threadHighhttps://learn.microsoft.com/en-us/dotnet/csharp/asynchronous-programming/
5656StylingDefine ThemeDictionaries for Light Dark and HighContrastResources placed inside ResourceDictionary.ThemeDictionaries entries are automatically swapped when the system theme changes — required for theme-aware brushesWrap brushes in a ThemeDictionaries dictionary keyed by Light Dark and HighContrast in App.xaml or page resourcesDefining a single brush at the root and missing dark/high-contrast variants<ResourceDictionary.ThemeDictionaries><ResourceDictionary x:Key="Light"><SolidColorBrush x:Key="Brand" Color="#005A9E"/></ResourceDictionary><ResourceDictionary x:Key="Dark"><SolidColorBrush x:Key="Brand" Color="#3A96DD"/></ResourceDictionary></ResourceDictionary.ThemeDictionaries><SolidColorBrush x:Key="Brand" Color="#005A9E"/> at root with no theme variantsMediumhttps://platform.uno/docs/articles/features/working-with-themes.html
5757ArchitectureUse Uno.Sdk with UnoFeaturesUno.Sdk is the modern single-project SDK that auto-resolves Uno.WinUI Uno.Toolkit Material and other packages from a UnoFeatures property — declare features by name instead of hand-managing dozens of PackageReferencesDeclare features in the csproj via <UnoFeatures>...</UnoFeatures> and let the SDK resolve transitive packagesHand-adding every Uno.* PackageReference and matching version numbers across packages<Project Sdk="Uno.Sdk"><PropertyGroup><UnoFeatures>Material;Hosting;Toolkit;Logging;MVVM</UnoFeatures></PropertyGroup></Project><PackageReference Include="Uno.WinUI"/><PackageReference Include="Uno.Material.WinUI"/> ... duplicated per feature with mismatched versionsMediumhttps://platform.uno/docs/articles/features/using-the-uno-sdk.html
5858LifecyclePersist desktop window state via Window.ClosedWinAppSDK and Skia desktop heads do not raise Application.Suspending — handle the Window.Closed event (and AppWindow size/position changes) to save user state when desktop apps shut downSubscribe to MainWindow.Closed and persist any unsaved state before the window is destroyedRelying on Application.Suspending to fire on desktop targetsm_window.Closed += (s, e) => SaveState();Application.Current.Suspending += SaveState; // never fires on WinAppSDK or Skia desktopMediumhttps://learn.microsoft.com/en-us/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window
5959ArchitectureUse WinRT.Interop for native window handle on WindowsCalling Win32 APIs from a WinUI Window (file pickers icon embedding etc.) requires the HWND — retrieve it via WinRT.Interop.WindowNative.GetWindowHandle and guard the call so non-Windows targets stay unaffectedGetWindowHandle inside a #if WINDOWS block when you need the HWNDCalling WinRT.Interop in shared code without a platform guard#if WINDOWS\nvar hWnd = WinRT.Interop.WindowNative.GetWindowHandle(MainWindow);\n#endifvar hWnd = WinRT.Interop.WindowNative.GetWindowHandle(MainWindow); // breaks build on iOS Android WASMMediumhttps://learn.microsoft.com/en-us/windows/apps/develop/ui/retrieve-hwnd