Eseguire la migrazione di un'app UWP a WinUI 3

La piattaforma UWP non è più in fase di sviluppo attivo. WinUI 3 e il SDK per app di Windows sono i suoi successori e gli strumenti di intelligenza artificiale possono automatizzare la maggior parte della migrazione. La sfida principale è che i modelli di intelligenza artificiale sono stati sottoposti a training su anni di esempi UWP, quindi senza indicazioni riproducono i modelli da cui si sta tentando di allontanarsi. Questa pagina fornisce all'agente il contesto necessario per farlo correttamente.

Installare il plug-in dell'agente WinUI

La winui-uwp-migration competenza gestisce automaticamente le sostituzioni comuni:

gh copilot plugin install winui@awesome-copilot

Per informazioni dettagliate, vedere il plug-in dell'agente WinUI .

Tabella di sostituzione API

Le tabelle seguenti riepilogano le sostituzioni API più comuni. Per la mappatura completa e dettagliata, inclusi membri, proprietà e API meno comuni, consulta Mappatura delle API e delle librerie UWP a SDK per app di Windows.

Important

x:Bind è impostato per impostazione predefinita su OneTime. A differenza di {Binding} (il cui valore predefinito è OneWay), x:Bind viene valutato una sola volta, a meno che non si specifichi Mode=OneWay o Mode=TwoWay. Durante la migrazione, verifica tutte le espressioni x:Bind associate a proprietà che cambiano in fase di esecuzione: l'assenza di Mode=OneWay causa bug del tipo "l'interfaccia utente non si aggiorna", invisibili in fase di compilazione.

Namespaces

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

Gestione dei thread

UWP WinUI 3
CoreDispatcher DispatcherQueue
Dispatcher.RunAsync(...) DispatcherQueue.TryEnqueue(...)
CoreApplication.MainView.CoreWindow.Dispatcher this.DispatcherQueue (da un Window o Page)

Windowing

UWP WinUI 3
ApplicationView AppWindow
ApplicationView.GetForCurrentView() AppWindow.GetFromWindowId(...)
ApplicationViewTitleBar AppWindowTitleBar
CoreWindow Microsoft.UI.Xaml.Window
SystemNavigationManager Pulsante Indietro tramite AppWindowTitleBar

Dialoghi e selezione

UWP WinUI 3
MessageDialog ContentDialog (imposta XamlRoot)
FileOpenPicker FileOpenPicker + InitializeWithWindow
FileSavePicker FileSavePicker + InitializeWithWindow
FolderPicker FolderPicker + InitializeWithWindow

Important

I selettori richiedono InitializeWithWindow prima di invocare PickSingleFileAsync (o simile):

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

ContentDialog richiede XamlRoot (non InitializeWithWindow):

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

Notifiche

UWP WinUI 3
Windows.UI.Notifications.ToastNotificationManager Microsoft.Windows.AppNotifications.AppNotificationManager
Windows.UI.Notifications.BadgeUpdateManager Microsoft.Windows.BadgeNotifications.BadgeNotificationManager
Windows.UI.Notifications.TileUpdateManager I riquadri sono deprecati: usare notifiche o widget

Rete e HTTP

UWP WinUI 3 (scelta consigliata)
Windows.Web.Http.HttpClient System.Net.Http.HttpClient (portabile, nessuna dipendenza WinRT)
Windows.Web.Syndication.SyndicationClient System.ServiceModel.Syndication.SyndicationFeed + HttpClient
Windows.Web.AtomPub.AtomPubClient System.ServiceModel.Syndication o HTTP diretto

Note

Le API HTTP WinRT (Windows.Web.Http) funzionano ancora nelle app WinUI 3 in pacchetto, ma gli equivalenti .NET sono consigliati per la portabilità, il debug più semplice e il supporto dell'ecosistema più ampio (middleware, DI, mocking).

UWP WinUI 3
Frame.Navigate(typeof(MyPage)) Frame.Navigate(typeof(MyPage)) — invariato
SystemNavigationManager.BackRequested Gestire tramite NavigationView o AppWindow
Windows.UI.Core.Preview.SystemNavigationManagerPreview AppWindow.Closing evento

Note

Navigazione hamburger personalizzata (SplitView + NavMenuListView): Molti esempi UWP implementavano la navigazione tramite un elemento AppShell.xaml con SplitView e un controllo NavMenuListView sviluppato manualmente (~500+ righe). In WinUI 3 sostituire questo modello intero con NavigationView, che fornisce la stessa esperienza utente con accessibilità predefinita, comportamento reattivo e supporto del pulsante indietro. Si tratta in genere di una riduzione del codice di 80%.

Modelli MVVM

UWP (implementazioni personalizzate comuni) WinUI 3 (scelta consigliata)
Personalizzato BindableBase / ObservableObject CommunityToolkit.Mvvm.ComponentModel.ObservableObject
Personalizzato DelegateCommand / RelayCommand CommunityToolkit.Mvvm.Input.RelayCommand
Manuale SetProperty + OnPropertyChanged [ObservableProperty] generatore di codice sorgente
INavigationService personalizzato Integrato Frame.Navigate + NavigationView

Tip

Il pacchetto NuGet CommunityToolkit.Mvvm è la base MVVM consigliata per le app WinUI 3. Sostituisce le classi base scritte manualmente con equivalenti testati generati dal codice sorgente, eliminando centinaia di righe di codice boilerplate.

dotnet add package CommunityToolkit.Mvvm

Ciclo di vita dell'app

UWP WinUI 3
Application.Current.Suspending Microsoft.Windows.AppLifecycle (richiede modifiche dell'architettura - vedere la nota)
Application.Current.Resuming AppInstance.GetCurrent().Activated (vedere la nota)
BackgroundTaskBuilder Le attività in background di SDK per app di Windows

Note

La migrazione del ciclo di vita dell'app WinUI 3 non è un semplice scambio di nomi API. Il SDK per app di Windows usa un modello di attivazione e sospensione diverso. Trattare il codice relativo al ciclo di vita come qualcosa che richiede una riscrittura dedicata anziché una sostituzione automatica. Per il modello completo, vedere la documentazione SDK per app di Windows ciclo di vita.

Impostazioni e archiviazione

UWP WinUI 3 (in pacchetto) WinUI 3 (senza pacchetto)
ApplicationData.Current.LocalSettings Invariato ❌ Genera : nessuna identità del pacchetto
ApplicationData.Current.LocalFolder Invariato ❌ Genera un'eccezione: nessun identificativo del pacchetto
Windows.Storage.KnownFolders Invariato ❌ Genera un errore: nessuna identità del pacchetto

Avvertimento

Le app senza pacchetto non possono usare ApplicationData.Current: genera un errore in fase di esecuzione perché non esiste alcuna identità del pacchetto. Usare invece API di file .NET standard:

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

Se la tua app UWP usava DataContractSerializer con [DataMember]/[IgnoreDataMember], valuta la possibilità di passare a System.Text.Json (più veloce, più leggero, con supporto per la generazione del codice sorgente). La mappatura degli attributi è:

  • [DataMember] [JsonPropertyName("name")] → (o usare direttamente i nomi delle proprietà)
  • [IgnoreDataMember][JsonIgnore]
  • [DataContract] → Nessuna necessità equivalente (System.Text.Json serializza le proprietà pubbliche per impostazione predefinita)

API che non cambiano

Windows.Devices.*, Windows.Media.*, Windows.UI.ViewManagement.UISettings, Windows.UI.Color e la maggior parte delle API WinRT all'esterno dello spazio dei nomi XAML rimane invariata.

Controlli senza un equivalente diretto

Alcuni controlli UWP non esistono in WinUI 3. Scegliere una sostituzione in base al proprio scenario:

Controllo UWP Sostituzione di WinUI 3 Notes
Pivot TabView, NavigationView (modalità superiore) o RadioButtons + visibilità Per 2-3 schede fisse, RadioButtons con la commutazione della visibilità è la soluzione più semplice. Per le schede dinamiche/chiudibili, usare TabView.
InkToolbar (sottoclasse personalizzata) CommandBar con AppBarToggleButton elementi Il modello predefinito InkToolbar esiste ma i modelli di sottoclasse personalizzati non vengono convertiti in modo pulito. Ricompilare barre degli strumenti personalizzate usando CommandBar.
RadialController Interoperabilità WinRT con handle di finestra RadialController.CreateForCurrentView() non ha equivalenti diretti. Uso di RadialControllerInterop con GetForWindow(hwnd).
SystemNavigationManager pulsante Indietro personalizzato o NavigationView.IsBackEnabled SystemNavigationManager.GetForCurrentView() non esiste. Aggiungi un pulsante Indietro personalizzato o usa il pulsante Indietro integrato di NavigationView.

input penna, Win2D e stampa

Questi sottosistemi richiedono passaggi di migrazione specifici oltre le modifiche dello spazio dei nomi.

Windows Ink

Le InkCanvas API e InkPresenter passano a Microsoft.UI.Input.Inking ma sono altrimenti identiche. Una modifica non ovvia è CoreInputDeviceTypes:

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

InkStrokeContainer.SaveAsync() e LoadAsync() richiedono IRandomAccessStreamancora . Ponte dai System.IO flussi:

// 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

Il nome del pacchetto Win2D è stato modificato ma la superficie dell'API è identica:

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

Tutte le Microsoft.Graphics.Canvas.* API (CanvasDevice, CanvasBitmap, CanvasRenderTarget, DrawInk) funzionano allo stesso modo. È necessario aggiornare solo il riferimento al pacchetto NuGet.

Stampa

La stampa UWP usa PrintManager.GetForCurrentView(). WinUI 3 richiede l'interoperabilità con l'handle di finestra:

// 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);

Le PrintDocument API di rendering (Paginate, GetPreviewPage, AddPages) sono invariate.

Important

Se si omette l'handle di finestra, PrintManagerInterop.GetForWindow genera un'eccezione COMException. Questo è lo stesso modello di interoperabilità di FileOpenPicker : qualsiasi API usata GetForCurrentView() in UWP richiede un handle di finestra in WinUI 3.

Prompt di avvio

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.

Modifiche ai file di progetto

Sostituire il framework di destinazione 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>

Aggiungere il pacchetto SDK per app di Windows:

dotnet add package Microsoft.WindowsAppSDK