winui3-migration-guide

Par github · awesome-copilot

Référence de migration UWP vers WinUI 3. Fait correspondre les API UWP héritées à leurs équivalents corrects dans le Windows App SDK, avec des extraits de code avant/après. Couvre les changements de namespace, le threading (CoreDispatcher vers DispatcherQueue), le système de fenêtrage (CoreWindow vers AppWindow), les boîtes de dialogue, les sélecteurs de fichiers, le partage, l'impression, les tâches en arrière-plan, ainsi que les erreurs de génération de code les plus fréquentes avec Copilot.

npx skills add https://github.com/github/awesome-copilot --skill winui3-migration-guide

Guide de Migration WinUI 3

Utilise cette compétence lors de la migration d'applications UWP vers WinUI 3 / Windows App SDK, ou pour vérifier que le code généré utilise les bonnes API WinUI 3 au lieu des anciens patterns UWP.


Changements de Namespace

Tous les namespaces Windows.UI.Xaml.* se déplacent vers Microsoft.UI.Xaml.* :

Namespace UWP Namespace 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.Xaml.Input Microsoft.UI.Xaml.Input
Windows.UI.Xaml.Data Microsoft.UI.Xaml.Data
Windows.UI.Xaml.Navigation Microsoft.UI.Xaml.Navigation
Windows.UI.Xaml.Shapes Microsoft.UI.Xaml.Shapes
Windows.UI.Composition Microsoft.UI.Composition
Windows.UI.Input Microsoft.UI.Input
Windows.UI.Colors Microsoft.UI.Colors
Windows.UI.Text Microsoft.UI.Text
Windows.UI.Core Microsoft.UI.Dispatching (pour le dispatcher)

Top 3 des Erreurs les Plus Courantes de Copilot

1. ContentDialog sans XamlRoot

// ❌ FAUX — Lève InvalidOperationException dans WinUI 3
var dialog = new ContentDialog
{
    Title = "Error",
    Content = "Something went wrong.",
    CloseButtonText = "OK"
};
await dialog.ShowAsync();
// ✅ CORRECT — Définir XamlRoot avant d'afficher
var dialog = new ContentDialog
{
    Title = "Error",
    Content = "Something went wrong.",
    CloseButtonText = "OK",
    XamlRoot = this.Content.XamlRoot  // Requis dans WinUI 3
};
await dialog.ShowAsync();

2. MessageDialog au lieu de ContentDialog

// ❌ FAUX — API UWP, non disponible dans le desktop WinUI 3
var dialog = new Windows.UI.Popups.MessageDialog("Are you sure?", "Confirm");
await dialog.ShowAsync();
// ✅ CORRECT — Utiliser ContentDialog
var dialog = new ContentDialog
{
    Title = "Confirm",
    Content = "Are you sure?",
    PrimaryButtonText = "Yes",
    CloseButtonText = "No",
    XamlRoot = this.Content.XamlRoot
};
var result = await dialog.ShowAsync();
if (result == ContentDialogResult.Primary)
{
    // Utilisateur confirmé
}

3. CoreDispatcher au lieu de DispatcherQueue

// ❌ FAUX — CoreDispatcher n'existe pas dans WinUI 3
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
    StatusText.Text = "Done";
});
// ✅ CORRECT — Utiliser DispatcherQueue
DispatcherQueue.TryEnqueue(() =>
{
    StatusText.Text = "Done";
});

// Avec priorité :
DispatcherQueue.TryEnqueue(DispatcherQueuePriority.High, () =>
{
    ProgressBar.Value = 100;
});

Migration de Windowing

Référence de Fenêtre

// ❌ FAUX — Window.Current n'existe pas dans WinUI 3
var currentWindow = Window.Current;
// ✅ CORRECT — Utiliser une propriété statique dans App
public partial class App : Application
{
    public static Window MainWindow { get; private set; }

    protected override void OnLaunched(LaunchActivatedEventArgs args)
    {
        MainWindow = new MainWindow();
        MainWindow.Activate();
    }
}
// Accéder partout : App.MainWindow

Gestion de Fenêtre

API UWP API WinUI 3
ApplicationView.TryResizeView() AppWindow.Resize()
AppWindow.TryCreateAsync() AppWindow.Create()
AppWindow.TryShowAsync() AppWindow.Show()
AppWindow.TryConsolidateAsync() AppWindow.Destroy()
AppWindow.RequestMoveXxx() AppWindow.Move()
AppWindow.GetPlacement() Propriété AppWindow.Position
AppWindow.RequestPresentation() AppWindow.SetPresenter()

Barre de Titre

API UWP API WinUI 3
CoreApplicationViewTitleBar AppWindowTitleBar
CoreApplicationView.TitleBar.ExtendViewIntoTitleBar AppWindow.TitleBar.ExtendsContentIntoTitleBar

Migration des Dialogues et Sélecteurs

Sélecteurs de Fichiers/Dossiers

// ❌ FAUX — Style UWP, pas de handle de fenêtre
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".txt");
var file = await picker.PickSingleFileAsync();
// ✅ CORRECT — Initialiser avec le handle de fenêtre
var picker = new FileOpenPicker();
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
picker.FileTypeFilter.Add(".txt");
var file = await picker.PickSingleFileAsync();

Migration du Threading

Pattern UWP Équivalent WinUI 3
CoreDispatcher.RunAsync(priority, callback) DispatcherQueue.TryEnqueue(priority, callback)
Dispatcher.HasThreadAccess DispatcherQueue.HasThreadAccess
CoreDispatcher.ProcessEvents() Pas d'équivalent — restructurer le code async
CoreWindow.GetForCurrentThread() Non disponible — utiliser DispatcherQueue.GetForCurrentThread()

Différence clé : UWP utilise ASTA (Application STA) avec blocage de réentrance intégré. WinUI 3 utilise STA standard sans cette protection. Attention aux problèmes de réentrance quand le code async traite les messages.


Migration des Tâches de Fond

// ❌ FAUX — IBackgroundTask UWP
public sealed class MyTask : IBackgroundTask
{
    public void Run(IBackgroundTaskInstance taskInstance) { }
}
// ✅ CORRECT — Windows App SDK AppLifecycle
using Microsoft.Windows.AppLifecycle;

// S'inscrire pour l'activation
var args = AppInstance.GetCurrent().GetActivatedEventArgs();
if (args.Kind == ExtendedActivationKind.AppNotification)
{
    // Gérer l'activation de fond
}

Migration des Paramètres d'Application

Scénario Application Empaquetée Application Non Empaquetée
Paramètres simples ApplicationData.Current.LocalSettings Fichier JSON dans LocalApplicationData
Stockage de fichiers local ApplicationData.Current.LocalFolder Environment.GetFolderPath(SpecialFolder.LocalApplicationData)

Remplacements de GetForCurrentView()

Tous les patterns GetForCurrentView() sont indisponibles dans les applications desktop WinUI 3 :

API UWP Remplacement WinUI 3
UIViewSettings.GetForCurrentView() Utiliser les propriétés AppWindow
ApplicationView.GetForCurrentView() AppWindow.GetFromWindowId(windowId)
DisplayInformation.GetForCurrentView() Win32 GetDpiForWindow() ou XamlRoot.RasterizationScale
CoreApplication.GetCurrentView() Non disponible — tracker les fenêtres manuellement
SystemNavigationManager.GetForCurrentView() Gérer la navigation arrière dans NavigationView directement

Migration des Tests

Les projets de test unitaire UWP ne fonctionnent pas avec WinUI 3. Tu dois migrer vers les modèles de projet de test WinUI 3.

UWP WinUI 3
Unit Test App (Universal Windows) Unit Test App (WinUI in Desktop)
Projet MSTest standard avec types UWP Doit utiliser l'application de test WinUI pour le runtime Xaml
[TestMethod] pour tous les tests [TestMethod] pour la logique, [UITestMethod] pour les tests XAML/UI
Class Library (Universal Windows) Class Library (WinUI in Desktop)
// ✅ Test unitaire WinUI 3 — utiliser [UITestMethod] pour toute interaction XAML
[UITestMethod]
public void TestMyControl()
{
    var control = new MyLibrary.MyUserControl();
    Assert.AreEqual(expected, control.MyProperty);
}

Clé : L'attribut [UITestMethod] indique au runner de test d'exécuter le test sur le thread UI XAML, ce qui est requis pour instancier n'importe quel type Microsoft.UI.Xaml.


Checklist de Migration

  1. [ ] Remplacer tous les directives using Windows.UI.Xaml.* par Microsoft.UI.Xaml.*
  2. [ ] Remplacer Windows.UI.Colors par Microsoft.UI.Colors
  3. [ ] Remplacer CoreDispatcher.RunAsync par DispatcherQueue.TryEnqueue
  4. [ ] Remplacer Window.Current par la propriété statique App.MainWindow
  5. [ ] Ajouter XamlRoot à toutes les instances de ContentDialog
  6. [ ] Initialiser tous les sélecteurs avec InitializeWithWindow.Initialize(picker, hwnd)
  7. [ ] Remplacer MessageDialog par ContentDialog
  8. [ ] Remplacer ApplicationView/CoreWindow par AppWindow
  9. [ ] Remplacer CoreApplicationViewTitleBar par AppWindowTitleBar
  10. [ ] Remplacer tous les appels GetForCurrentView() par des équivalents AppWindow
  11. [ ] Mettre à jour l'interop pour les gestionnaires de Partage et Impression
  12. [ ] Remplacer IBackgroundTask par l'activation AppLifecycle
  13. [ ] Mettre à jour le fichier projet : TFM à net10.0-windows10.0.22621.0, ajouter <UseWinUI>true</UseWinUI>
  14. [ ] Migrer les tests unitaires vers le projet Unit Test App (WinUI in Desktop) ; utiliser [UITestMethod] pour les tests XAML
  15. [ ] Tester les configurations empaquetée et non empaquetée

Skills similaires