Migrar uma aplicação UWP para o WinUI 3

A UWP já não está em desenvolvimento ativo. O WinUI 3 e o SDK de Aplicações Windows são os seus sucessores — e as ferramentas de IA podem automatizar a maior parte da migração. O principal desafio é que os modelos de IA foram treinados com anos de amostras UWP, por isso, sem orientação, eles reproduzem os padrões de que estás a tentar afastar-te. Esta página fornece ao seu agente o contexto de que necessita para fazer as coisas corretamente.

Instale o plugin do agente WinUI

A winui-uwp-migration habilidade trata automaticamente das substituições comuns:

gh copilot plugin install winui@awesome-copilot

Consulte o plugin do agente WinUI para todos os detalhes.

Tabela de substituição de API

As tabelas seguintes resumem as substituições de API mais comuns. Para o mapeamento detalhado completo — incluindo membros, propriedades e APIs menos comuns — veja Mapear APIs e bibliotecas UWP para o SDK de Aplicações Windows.

Importante

x:Bind está, por predefinição, no modo OneTime. Ao contrário de {Binding} (que, por predefinição, utiliza OneWay), x:Bind só é avaliado uma vez, a menos que especifique Mode=OneWay ou Mode=TwoWay. Durante a migração, reveja todas as expressões x:Bind que estão associadas a propriedades que mudam em tempo de execução — a ausência de Mode=OneWay causa erros do tipo «a IU não é atualizada» que passam despercebidos na compilação.

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

Encadeamento

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

Windowing

UWP WinUI 3
ApplicationView AppWindow
ApplicationView.GetForCurrentView() AppWindow.GetFromWindowId(...)
ApplicationViewTitleBar AppWindowTitleBar
CoreWindow Microsoft.UI.Xaml.Window
SystemNavigationManager Botão de voltar via AppWindowTitleBar

Diálogos e seletores

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

Importante

Os selecionadores requerem InitializeWithWindow antes de chamar PickSingleFileAsync (ou semelhante):

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

ContentDialog requer XamlRoot (não 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 Os mosaicos foram preteridos — utilize notificações ou widgets

Rede e HTTP

UWP WinUI 3 (recomendado)
Windows.Web.Http.HttpClient System.Net.Http.HttpClient (portátil, sem dependência do WinRT)
Windows.Web.Syndication.SyndicationClient System.ServiceModel.Syndication.SyndicationFeed + HttpClient
Windows.Web.AtomPub.AtomPubClient System.ServiceModel.Syndication ou HTTP direto

Note

As APIs HTTP do WinRT (Windows.Web.Http) ainda funcionam em aplicações WinUI 3 empacotadas, mas os equivalentes .NET são recomendados para portabilidade, depuração mais simples e suporte mais amplo ao ecossistema (middleware, DI, mocking).

UWP WinUI 3
Frame.Navigate(typeof(MyPage)) Frame.Navigate(typeof(MyPage)) — inalterado
SystemNavigationManager.BackRequested Manipular via NavigationView ou AppWindow
Windows.UI.Core.Preview.SystemNavigationManagerPreview evento AppWindow.Closing

Note

Navegação personalizada com menu hambúrguer (SplitView + NavMenuListView): Muitos exemplos de UWP implementaram a navegação usando um AppShell.xaml personalizado com SplitView e um controlo NavMenuListView desenvolvido manualmente (~500+ linhas). No WinUI 3, substitua todo este padrão pelo NavigationView, que oferece a mesma experiência de utilizador com acessibilidade incorporada, comportamento responsivo e suporte para botões retroativos. Isto é tipicamente uma redução de 80% no código.

Padrões MVVM

UWP (implementações personalizadas comuns) WinUI 3 (recomendado)
Personalizado BindableBase / ObservableObject CommunityToolkit.Mvvm.ComponentModel.ObservableObject
Personalizado DelegateCommand / RelayCommand CommunityToolkit.Mvvm.Input.RelayCommand
Manual SetProperty + OnPropertyChanged [ObservableProperty] Gerador de fonte
Personalizado INavigationService Integrado Frame.Navigate + NavigationView

Tip

O pacote NuGet CommunityToolkit.Mvvm é a base recomendada MVVM para aplicações WinUI 3. Substitui as classes de base criadas manualmente por equivalentes testados e gerados a partir do código-fonte — eliminando centenas de linhas de código repetitivo.

dotnet add package CommunityToolkit.Mvvm

Ciclo de vida do aplicativo

UWP WinUI 3
Application.Current.Suspending Microsoft.Windows.AppLifecycle (requer alterações arquitetónicas — ver nota)
Application.Current.Resuming AppInstance.GetCurrent().Activated (ver nota)
BackgroundTaskBuilder SDK de Aplicações Windows: tarefas em segundo plano

Note

A migração do ciclo de vida da aplicação WinUI 3 não é uma simples troca de nomes de API. O SDK de Aplicações Windows utiliza um modelo diferente de ativação e suspensão. Trate o código do ciclo de vida como se exigisse uma reescrita dedicada em vez de substituição automática. Consulte a documentação do ciclo de vida SDK de Aplicações Windows para o modelo completo.

Definições e armazenamento

UWP WinUI 3 (embalado) WinUI 3 (não embalado)
ApplicationData.Current.LocalSettings Inalterado ❌ Gera erro — sem identidade de pacote
ApplicationData.Current.LocalFolder Inalterado ❌ Lançamentos — sem identidade de pacote
Windows.Storage.KnownFolders Inalterado ❌ Gera um erro — sem identidade do pacote

Warning

As aplicações não empacotadas não podem usar ApplicationData.Current — gera um erro em tempo de execução porque não há identidade de pacote. Use APIs padrão de ficheiros .NET em vez disso:

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 a sua aplicação UWP usava DataContractSerializer com [DataMember]/[IgnoreDataMember], considere migrar para System.Text.Json (mais rápida, mais compacta, com suporte para geração de código). O mapeamento de atributos é:

  • [DataMember][JsonPropertyName("name")] (ou simplesmente usar nomes de propriedades diretamente)
  • [IgnoreDataMember][JsonIgnore]
  • [DataContract] → Não é necessário equivalente (System.Text.Json serializa propriedades públicas por defeito)

APIs que não mudam

Windows.Devices.*, Windows.Media.*, Windows.UI.ViewManagement.UISettings, Windows.UI.Color e a maioria das APIs WinRT fora do espaço de nomes XAML mantêm-se inalteradas.

Controlos sem equivalente direto

Alguns controlos UWP não existem no WinUI 3. Escolha um substituto com base no seu cenário:

Controlo UWP Alternativa ao WinUI 3 Observações
Pivot TabView, NavigationView (modo superior), ou RadioButtons + visibilidade Para 2–3 abas fixas, RadioButtons com comutação de visibilidade é o mais simples. Para separadores dinâmicos/que podem ser fechados, use TabView.
InkToolbar (subclasse personalizada) CommandBar com AppBarToggleButton itens A funcionalidade integrada InkToolbar existe, mas os padrões personalizados de derivação de subclasses não são facilmente adaptáveis. Reconstrua barras de ferramentas personalizadas usando CommandBar.
RadialController Interoperação WinRT com controlo de janela RadialController.CreateForCurrentView() não tem equivalente direto. Utilizar o RadialControllerInterop com o GetForWindow(hwnd).
SystemNavigationManager Botão traseiro personalizado ou NavigationView.IsBackEnabled SystemNavigationManager.GetForCurrentView() não existe. Adiciona o teu próprio botão de retrocesso ou usa o botão de retrocesso incorporado do NavigationView.

Tinta, Win2D e impressão

Estes subsistemas requerem passos específicos de migração para além das alterações no namespace.

Tinta do Windows

As InkCanvas APIs e InkPresenter mudam-se para Microsoft.UI.Input.Inking mas são idênticas de resto. A única alteração não óbvia é CoreInputDeviceTypes:

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

InkStrokeContainer.SaveAsync() e LoadAsync() ainda assim requerem IRandomAccessStream. Ponte a partir dos System.IO ribeiros:

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

O nome do pacote Win2D mudou, mas a superfície da API é idêntica:

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

Todas Microsoft.Graphics.Canvas.* as APIs (CanvasDevice, CanvasBitmap, CanvasRenderTarget, DrawInk) funcionam da mesma forma. Só a referência do pacote NuGet precisa de ser atualizada.

Impressão

A impressão UWP utiliza PrintManager.GetForCurrentView(). O WinUI 3 requer interoperação entre janelas:

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

As PrintDocument APIs de renderização (Paginate, GetPreviewPage, AddPages) mantêm-se inalteradas.

Importante

Se omitir o identificador da janela, PrintManagerInterop.GetForWindow gera uma COMException. Este é o mesmo padrão de interoperabilidade que FileOpenPicker — qualquer API que usava GetForCurrentView() em UWP precisa de um identificador de janela no WinUI 3.

Prompt inicial

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.

Alterações no ficheiro Project

Substituir a estrutura alvo do 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>

Adicionar o pacote do SDK de Aplicações Windows:

dotnet add package Microsoft.WindowsAppSDK