Migrer une application UWP vers WinUI 3

UWP n’est plus en cours de développement actif. WinUI 3 et le SDK d'application Windows sont ses successeurs, et les outils IA peuvent automatiser la majeure partie de la migration. Le principal défi est que les modèles IA ont été formés sur des années d’échantillons UWP. Par conséquent, sans conseils, ils reproduisent les modèles que vous essayez de quitter. Cette page fournit à votre agent le contexte dont il a besoin pour bien faire les choses.

Installer le plug-in de l’agent WinUI

La winui-uwp-migration compétence gère automatiquement les substitutions courantes :

gh copilot plugin install winui@awesome-copilot

Pour plus d’informations, consultez le plug-in de l’agent WinUI .

Table de substitution d’API

Les tableaux suivants résument les substitutions d’API les plus courantes. Pour obtenir le mappage complet et détaillé — y compris les membres, les propriétés et les API moins courantes — consultez Mappage des API et bibliothèques UWP vers le SDK d'application Windows.

Important

x:Bind est en mode OneTime par défaut. Contrairement {Binding} à (ce qui est défini par défaut OneWay), x:Bind n’évalue qu’une seule fois, sauf si vous spécifiez Mode=OneWay ou Mode=TwoWay. Pendant la migration, auditez toutes les expressions x:Bind qui sont liées à des propriétés qui changent à l’exécution — l’absence de Mode=OneWay provoque des bogues du type « l’interface utilisateur ne se met pas à jour », invisibles à la compilation.

Espaces de noms

UWP WinUI 3
Windows.UI.Xaml.* Microsoft.UI.Xaml.*
Windows.UI.Xaml.Controls.* Microsoft.UI.Xaml.Controls.*
Windows.UI.Xaml.Media.* Microsoft.UI.Xaml.Media.*
Windows.UI.Composition Microsoft.UI.Composition

Thread

UWP WinUI 3
CoreDispatcher DispatcherQueue
Dispatcher.RunAsync(...) DispatcherQueue.TryEnqueue(...)
CoreApplication.MainView.CoreWindow.Dispatcher this.DispatcherQueue (à partir d’un Window ou Page)

Windowing

UWP WinUI 3
ApplicationView AppWindow
ApplicationView.GetForCurrentView() AppWindow.GetFromWindowId(...)
ApplicationViewTitleBar AppWindowTitleBar
CoreWindow Microsoft.UI.Xaml.Window
SystemNavigationManager Bouton Retour via AppWindowTitleBar

Boîtes de dialogue et sélecteurs

UWP WinUI 3
MessageDialog ContentDialog (défini XamlRoot)
FileOpenPicker FileOpenPicker + InitializeWithWindow
FileSavePicker FileSavePicker + InitializeWithWindow
FolderPicker FolderPicker + InitializeWithWindow

Important

Les sélecteurs nécessitent InitializeWithWindow avant l’appel PickSingleFileAsync (ou similaire) :

var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);

ContentDialog nécessite XamlRoot (pas InitializeWithWindow) :

var dialog = new ContentDialog { XamlRoot = this.Content.XamlRoot, ... };
await dialog.ShowAsync();

Notifications

UWP WinUI 3
Windows.UI.Notifications.ToastNotificationManager Microsoft.Windows.AppNotifications.AppNotificationManager
Windows.UI.Notifications.BadgeUpdateManager Microsoft.Windows.BadgeNotifications.BadgeNotificationManager
Windows.UI.Notifications.TileUpdateManager Les vignettes sont déconseillées : utiliser des notifications ou des widgets

Mise en réseau et HTTP

UWP WinUI 3 (recommandé)
Windows.Web.Http.HttpClient System.Net.Http.HttpClient (portable, aucune dépendance WinRT)
Windows.Web.Syndication.SyndicationClient System.ServiceModel.Syndication.SyndicationFeed + HttpClient
Windows.Web.AtomPub.AtomPubClient System.ServiceModel.Syndication ou HTTP direct

Note

Les API HTTP WinRT (Windows.Web.Http) fonctionnent toujours dans les applications WinUI 3 empaquetées, mais les .NET équivalents sont recommandés pour la portabilité, le débogage plus simple et la prise en charge de l’écosystème plus large (middleware, DI, mocking).

UWP WinUI 3
Frame.Navigate(typeof(MyPage)) Frame.Navigate(typeof(MyPage)) — inchangé
SystemNavigationManager.BackRequested Gérer via NavigationView ou AppWindow
Windows.UI.Core.Preview.SystemNavigationManagerPreview événement AppWindow.Closing

Note

Navigation hamburger personnalisée (SplitView + NavMenuListView) : de nombreux exemples UWP implémentaient la navigation à l’aide d’un fichier AppShell.xaml personnalisé avec SplitView et un contrôle NavMenuListView développé manuellement (plus de 500 lignes environ). Dans WinUI 3, remplacez ce modèle entier par NavigationView, qui fournit la même expérience utilisateur avec l’accessibilité intégrée, le comportement réactif et la prise en charge des boutons précédents. Il s’agit généralement d’une réduction de code de 80 %.

Modèles MVVM

UWP (implémentations personnalisées courantes) WinUI 3 (recommandé)
Personnalisé BindableBase / ObservableObject CommunityToolkit.Mvvm.ComponentModel.ObservableObject
Personnalisé DelegateCommand / RelayCommand CommunityToolkit.Mvvm.Input.RelayCommand
Manuelle SetProperty + OnPropertyChanged [ObservableProperty] générateur de code source
INavigationService personnalisé Intégré Frame.Navigate + NavigationView

Tip

Le package NuGet CommunityToolkit.Mvvm est la base MVVM recommandée pour les applications WinUI 3. Il remplace les classes de base codées à la main par des équivalents testés et générés automatiquement à partir du code source, éliminant ainsi des centaines de lignes de code répétitif.

dotnet add package CommunityToolkit.Mvvm

Cycle de vie de l’application

UWP WinUI 3
Application.Current.Suspending Microsoft.Windows.AppLifecycle (nécessite des modifications architecturales - voir remarque)
Application.Current.Resuming AppInstance.GetCurrent().Activated (voir remarque)
BackgroundTaskBuilder Tâches en arrière-plan du SDK d'application Windows

Note

La migration du cycle de vie des applications WinUI 3 n’est pas un échange simple de nom d’API. Le SDK d'application Windows utilise un modèle d’activation et de suspension différent. Traitez le code de cycle de vie comme nécessitant une réécriture dédiée plutôt que la substitution automatisée. Consultez la documentation de cycle de vie SDK d'application Windows pour le modèle complet.

Paramètres et stockage

UWP WinUI 3 (empaqueté) WinUI 3 (non empaqueté)
ApplicationData.Current.LocalSettings Inchangé ❌ Lève une exception — aucune identité de package
ApplicationData.Current.LocalFolder Inchangé ❌ Lève une exception — aucune identité de package
Windows.Storage.KnownFolders Inchangé ❌ Lève une exception — aucune identité de package

Warning

Les applications non empaquetées ne peuvent pas utiliser ApplicationData.Current : cela génère une erreur à l’exécution, car il n’existe pas d’identité de package. Utilisez les API de fichier .NET standard à la place :

var appData = Path.Combine(
    Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
    "YourAppName");
Directory.CreateDirectory(appData);
var json = JsonSerializer.Serialize(data);
await File.WriteAllTextAsync(Path.Combine(appData, "settings.json"), json);

Note

Si votre application UWP utilisait DataContractSerializer avec [DataMember]/[IgnoreDataMember], envisagez de migrer vers System.Text.Json (plus rapide, plus léger, avec prise en charge de la génération de code source). Le mappage d’attributs est :

  • [DataMember] [JsonPropertyName("name")] → (ou utilisez simplement des noms de propriétés directement)
  • [IgnoreDataMember][JsonIgnore]
  • [DataContract] → Aucun équivalent nécessaire (System.Text.Json sérialise les propriétés publiques par défaut)

API qui ne changent pas

Windows.Devices.*, Windows.Media.*, Windows.UI.ViewManagement.UISettings, Windows.UI.Color et la plupart des API WinRT en dehors de l’espace de noms XAML sont inchangées.

Contrôles sans équivalent direct

Certains contrôles UWP n’existent pas dans WinUI 3. Choisissez un remplacement en fonction de votre scénario :

Contrôle UWP Remplacement de WinUI 3 Remarques
Pivot TabView, NavigationView (mode supérieur) ou RadioButtons + visibilité Pour 2 à 3 onglets fixes, RadioButtons avec changement de visibilité est la solution la plus simple. Pour les onglets dynamiques/fermables, utilisez TabView.
InkToolbar (sous-classe personnalisée) CommandBar avec des éléments AppBarToggleButton Les modèles intégrés existent, mais les modèles de sous-classification InkToolbar personnalisés ne se traduisent pas correctement. Reconstruire des barres d’outils personnalisées à l’aide de CommandBar.
RadialController Interopérabilité WinRT avec handle de fenêtre RadialController.CreateForCurrentView() n’a pas d’équivalent direct. utiliser RadialControllerInterop avec GetForWindow(hwnd) ;
SystemNavigationManager Bouton Retour personnalisé ou NavigationView.IsBackEnabled SystemNavigationManager.GetForCurrentView() n’existe pas. Ajoutez votre propre bouton de retour ou utilisez le bouton de retour intégré de NavigationView.

Encre, Win2D et impression

Ces sous-systèmes nécessitent des étapes de migration spécifiques au-delà des modifications apportées à l’espace de noms.

Windows Ink

Les API InkCanvas et InkPresenter sont déplacées vers Microsoft.UI.Input.Inking, mais sont par ailleurs identiques. Le changement non évident est CoreInputDeviceTypes:

UWP WinUI 3
Windows.UI.Input.Inking.* Microsoft.UI.Input.Inking.*
Windows.UI.Core.CoreInputDeviceTypes Microsoft.UI.Core.CoreInputDeviceTypes

InkStrokeContainer.SaveAsync() et LoadAsync() nécessitent toujours IRandomAccessStream. Pont à partir de flux System.IO :

// Saving ink strokes to a file using System.IO
using var memoryStream = new MemoryStream();
using var ras = memoryStream.AsRandomAccessStream();
await inkStrokeContainer.SaveAsync(ras);
await File.WriteAllBytesAsync(filePath, memoryStream.ToArray());

// Loading ink strokes from a file
var bytes = await File.ReadAllBytesAsync(filePath);
using var ms = new MemoryStream(bytes);
using var ras = ms.AsRandomAccessStream();
await inkStrokeContainer.LoadAsync(ras);

Win2D

Le nom du package Win2D a changé, mais la surface de l’API est identique :

UWP WinUI 3
Win2D.uwp (NuGet) Microsoft.Graphics.Win2D (NuGet)

Toutes les Microsoft.Graphics.Canvas.* API (CanvasDevice, , CanvasBitmapCanvasRenderTarget, DrawInk) fonctionnent de la même façon. Seule la référence du package NuGet doit être mise à jour.

Impression

L’impression UWP utilise PrintManager.GetForCurrentView(). WinUI 3 nécessite l’interopérabilité du handle de fenêtre :

// UWP
var printManager = PrintManager.GetForCurrentView();
printManager.PrintTaskRequested += OnPrintTaskRequested;
await PrintManager.ShowPrintUIAsync();

// WinUI 3 — must pass window handle
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
var printManager = PrintManagerInterop.GetForWindow(hwnd);
printManager.PrintTaskRequested += OnPrintTaskRequested;
await PrintManagerInterop.ShowPrintUIForWindowAsync(hwnd);

Les PrintDocument API de rendu (Paginate, , GetPreviewPageAddPages) sont inchangées.

Important

Si vous omettez le handle de fenêtre, PrintManagerInterop.GetForWindow lève une COMException. Il s’agit du même modèle d’interopérabilité que FileOpenPicker : toute API utilisée GetForCurrentView() dans UWP a besoin d’un handle de fenêtre dans WinUI 3.

Requête de démarrage

I'm migrating a UWP app to WinUI 3 using the Windows App SDK.

Apply these substitutions:
- Windows.UI.Xaml.* → Microsoft.UI.Xaml.*
- CoreDispatcher / Dispatcher.RunAsync → DispatcherQueue.TryEnqueue
- ApplicationView → AppWindow + AppWindowTitleBar
- CoreWindow → Microsoft.UI.Xaml.Window
- MessageDialog → ContentDialog (set XamlRoot, not InitializeWithWindow)
- FileOpenPicker / FileSavePicker / FolderPicker → add InitializeWithWindow
- Windows.UI.Notifications → Microsoft.Windows.AppNotifications
- SystemNavigationManager.BackRequested → NavigationView back handling
- Pivot → TabView, NavigationView (top mode), or RadioButtons (no direct equivalent)
- InkToolbar custom subclasses → rebuild as CommandBar with AppBarToggleButton
- PrintManager.GetForCurrentView → PrintManagerInterop.GetForWindow(hwnd)
- Win2D.uwp NuGet → Microsoft.Graphics.Win2D NuGet
- Windows.UI.Input.Inking.* → Microsoft.UI.Input.Inking.*

Do not use any Windows.UI.Xaml.* namespaces in new code.
Do not use CoreDispatcher — use DispatcherQueue.
x:Bind defaults to Mode=OneTime. Add Mode=OneWay for any binding that should update at runtime.
Flag any APIs without a direct WinUI 3 equivalent rather than guessing.

modifications apportées au fichier Project

Remplacez le framework cible UWP :

<!-- Before (UWP) -->
<TargetPlatformVersion>10.0.19041.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>

<!-- After (WinUI 3) -->
<TargetFramework>net10.0-windows10.0.19041.0</TargetFramework>
<WindowsSdkPackageVersion>10.0.19041.31</WindowsSdkPackageVersion>

Ajoutez le package SDK d'application Windows :

dotnet add package Microsoft.WindowsAppSDK