Migración de una aplicación para UWP a WinUI 3

UWP ya no está en desarrollo activo. WinUI 3 y el SDK de Aplicaciones para Windows son sus sucesores, y las herramientas de inteligencia artificial pueden automatizar la mayor parte de la migración. El principal desafío es que los modelos de inteligencia artificial se entrenaron en años de ejemplos de UWP, por lo que sin instrucciones reproducen los patrones de los que intentas alejarte. Esta página proporciona a tu agente el contexto que necesita para hacerlo bien.

Instalación del complemento del agente de WinUI

La winui-uwp-migration función gestiona automáticamente las sustituciones comunes:

gh copilot plugin install winui@awesome-copilot

Consulte el complemento del agente de WinUI para obtener todos los detalles.

Tabla de sustitución de API

En las tablas siguientes se resumen las sustituciones de API más comunes. Para obtener la asignación detallada completa (incluidos los miembros, las propiedades y las API menos comunes), consulta Asignación de API y bibliotecas de UWP a la SDK de Aplicaciones para Windows.

Importante

x:Bind está en modo OneTime de forma predeterminada. A diferencia {Binding} de (que tiene OneWaycomo valor predeterminado ), x:Bind solo se evalúa una vez a menos que especifique Mode=OneWay o Mode=TwoWay. Durante la migración, audite todas las expresiones x:Bind que están vinculadas a propiedades que cambian durante la ejecución; la ausencia de Mode=OneWay provoca errores de "la interfaz de usuario no se actualiza" que son indetectables en tiempo de compilación.

Espacios de nombres

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

Threading

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

Windowing

UWP WinUI 3
ApplicationView AppWindow
ApplicationView.GetForCurrentView() AppWindow.GetFromWindowId(...)
ApplicationViewTitleBar AppWindowTitleBar
CoreWindow Microsoft.UI.Xaml.Window
SystemNavigationManager Botón de retroceso mediante AppWindowTitleBar

Cuadros de diálogo y selectores

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

Importante

Los selectores requieren InitializeWithWindow antes de llamar a PickSingleFileAsync (o algo similar):

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

ContentDialog requiere XamlRoot (no InitializeWithWindow):

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

Notificaciones

UWP WinUI 3
Windows.UI.Notifications.ToastNotificationManager Microsoft.Windows.AppNotifications.AppNotificationManager
Windows.UI.Notifications.BadgeUpdateManager Microsoft.Windows.BadgeNotifications.BadgeNotificationManager
Windows.UI.Notifications.TileUpdateManager Los iconos están en desuso: usar notificaciones o widgets

Redes y HTTP

UWP WinUI 3 (recomendado)
Windows.Web.Http.HttpClient System.Net.Http.HttpClient (portable, sin dependencia de WinRT)
Windows.Web.Syndication.SyndicationClient System.ServiceModel.Syndication.SyndicationFeed + HttpClient
Windows.Web.AtomPub.AtomPubClient System.ServiceModel.Syndication o HTTP directa

Note

Las API HTTP de WinRT (Windows.Web.Http) siguen funcionando en aplicaciones WinUI 3 empaquetadas, pero se recomiendan los equivalentes de .NET por motivos de portabilidad, una depuración más sencilla y una compatibilidad más amplia con el ecosistema (middleware, inyección de dependencias, simulación).

UWP WinUI 3
Frame.Navigate(typeof(MyPage)) Frame.Navigate(typeof(MyPage)) — sin cambios
SystemNavigationManager.BackRequested Gestionar mediante NavigationView o AppWindow
Windows.UI.Core.Preview.SystemNavigationManagerPreview AppWindow.Closing evento

Note

Navegación tipo hamburguesa personalizada (SplitView + NavMenuListView): Muchos ejemplos de UWP implementaban la navegación mediante un AppShell.xaml personalizado con SplitView y un control NavMenuListView creado a mano (más de 500 líneas). En WinUI 3, reemplace todo este patrón por NavigationView, que proporciona la misma experiencia de usuario con accesibilidad integrada, comportamiento dinámico y compatibilidad con botón atrás. Normalmente, se trata de una reducción de código de 80%.

Patrones de MVVM

UWP (implementaciones personalizadas comunes) WinUI 3 (recomendado)
Personalizado BindableBase / ObservableObject CommunityToolkit.Mvvm.ComponentModel.ObservableObject
Personalizado DelegateCommand / RelayCommand CommunityToolkit.Mvvm.Input.RelayCommand
Manual SetProperty + OnPropertyChanged [ObservableProperty] generador de código fuente
INavigationService personalizado Integrado Frame.Navigate + NavigationView

Sugerencia

El paquete NuGet CommunityToolkit.Mvvm es la base de MVVM recomendada para aplicaciones winUI 3. Reemplaza las clases base hechas manualmente por equivalentes probados generados a partir del código fuente, eliminando cientos de líneas de código repetitivo.

dotnet add package CommunityToolkit.Mvvm

Ciclo de vida de la aplicación

UWP WinUI 3
Application.Current.Suspending Microsoft.Windows.AppLifecycle (requiere cambios arquitectónicos; consulte la nota)
Application.Current.Resuming AppInstance.GetCurrent().Activated (consulte la nota)
BackgroundTaskBuilder Tareas en segundo plano del SDK de aplicaciones de Windows

Note

La migración del ciclo de vida de aplicaciones de WinUI 3 no es un intercambio simple de nombres de API. El SDK de Aplicaciones para Windows usa un modelo de activación y suspensión diferente. Trate el código del ciclo de vida como algo que requiere una reescritura específica en lugar de una sustitución automatizada. Consulte la documentación del ciclo de vida de SDK de Aplicaciones para Windows para ver el modelo completo.

Configuración y almacenamiento

UWP WinUI 3 (empaquetado) WinUI 3 (sin empaquetar)
ApplicationData.Current.LocalSettings Sin cambios ❌ Lanza una excepción: falta identidad del paquete
ApplicationData.Current.LocalFolder Sin cambios ❌ Lanza una excepción: falta identidad del paquete
Windows.Storage.KnownFolders Sin cambios ❌ Lanza una excepción: falta identidad del paquete

Warning

Las aplicaciones desempaquetadas no pueden usar ApplicationData.Current: genera un error en tiempo de ejecución porque no existe identidad de paquete. En su lugar, use las API de archivo .NET estándar:

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 tu aplicación para UWP usaba DataContractSerializer con [DataMember]/[IgnoreDataMember], considera migrar a System.Text.Json (más rápido, más pequeño y compatible con la generación de código fuente). La asignación de atributos es:

  • [DataMember][JsonPropertyName("name")] (o simplemente usar los nombres de las propiedades directamente)
  • [IgnoreDataMember][JsonIgnore]
  • [DataContract] → No se necesita ningún equivalente (System.Text.Json serializa las propiedades públicas de forma predeterminada)

API que no cambian

Windows.Devices.*, Windows.Media.*, Windows.UI.ViewManagement.UISettings, Windows.UI.Color y la mayoría de las API de WinRT fuera del espacio de nombres XAML no cambian.

Controles sin un equivalente directo

Algunos controles de UWP no existen en WinUI 3. Elija un reemplazo en función de su escenario:

Control de UWP Reemplazo de WinUI 3 Notas
Pivot TabView, NavigationView (modo superior) o RadioButtons + visibilidad Para 2 o 3 pestañas fijas, RadioButtons con alternancia de visibilidad es lo más sencillo. Para las pestañas dinámicas o que se pueden cerrar, use TabView.
InkToolbar (subclase personalizada) CommandBar con AppBarToggleButton elementos El elemento integrado InkToolbar existe, pero los patrones de subclases personalizados no se traducen de forma limpia. Recompile las barras de herramientas personalizadas mediante CommandBar.
RadialController Interoperabilidad de WinRT con identificador de ventana RadialController.CreateForCurrentView() no tiene equivalente directo. Usar RadialControllerInterop con GetForWindow(hwnd).
SystemNavigationManager Botón de retroceso personalizado o NavigationView.IsBackEnabled SystemNavigationManager.GetForCurrentView() no existe. Añada su propio botón de retroceso o use el botón de retroceso integrado de NavigationView.

Ink, Win2D e impresión

Estos subsistemas requieren pasos de migración específicos más allá de los cambios en el espacio de nombres.

Windows Ink

Las InkCanvas API y InkPresenter se trasladan a Microsoft.UI.Input.Inking, pero por lo demás son idénticas. El cambio no obvio es CoreInputDeviceTypes:

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

InkStrokeContainer.SaveAsync() y LoadAsync() todavía requieren IRandomAccessStream. Puente desde flujos 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

El nombre del paquete Win2D cambió, pero la superficie de API es idéntica:

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

Todas las Microsoft.Graphics.Canvas.* API (CanvasDevice, CanvasBitmap, CanvasRenderTarget, DrawInk) funcionan de la misma manera. Solo la referencia del paquete NuGet necesita actualizarse.

Impresión

La impresión de UWP utiliza PrintManager.GetForCurrentView(). WinUI 3 requiere interoperabilidad con el identificador de ventana:

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

Las PrintDocument API de representación (Paginate, GetPreviewPage, AddPages) no se modifican.

Importante

Si omites el identificador de ventana, PrintManagerInterop.GetForWindow lanza un COMException. Este es el mismo patrón de interoperabilidad que FileOpenPicker: cualquier API que usaba GetForCurrentView() en UWP necesita un identificador de ventana en WinUI 3.

Mensaje de inicio

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.

Cambios en el archivo del proyecto

Reemplazar el marco de destino de 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>

Agregue el paquete SDK de Aplicaciones para Windows:

dotnet add package Microsoft.WindowsAppSDK