Migrar um aplicativo UWP para o WinUI 3

A UWP não está mais em desenvolvimento ativo. O WinUI 3 e o SDK do Aplicativo Windows são 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 em anos de exemplos UWP, portanto, sem orientação, eles reproduzem os padrões dos quais você está tentando se afastar. Esta página fornece ao seu agente o contexto necessário para acertar.

Instalar o plug-in do agente WinUI

A habilidade winui-uwp-migration faz automaticamente as substituições comuns:

gh copilot plugin install winui@awesome-copilot

Consulte o plug-in do agente WinUI para obter detalhes completos.

Tabela de substituição de API

As tabelas a seguir resumem as substituições de API mais comuns. Para obter o mapeamento completo e detalhado — incluindo membros, propriedades e APIs menos comuns — consulte Mapeando APIs e bibliotecas UWP para o SDK do Aplicativo Windows.

Importante

x:Bind usa o modo OneTime por padrão. Diferentemente {Binding} (que usa como padrão OneWay), x:Bind só é avaliado uma vez, a menos que você especifique Mode=OneWay ou Mode=TwoWay. Durante a migração, audite todas as expressões x:Bind que se vinculam a propriedades que mudam em tempo de execução — a ausência de Mode=OneWay causa bugs de "a interface do usuário não é atualizada" que são invisíveis em tempo de 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

Threading

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 Voltar por meio de AppWindowTitleBar

Caixas de diálogo e seletores

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

Importante

Os seletores exigem 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();

Notificações

UWP WinUI 3
Windows.UI.Notifications.ToastNotificationManager Microsoft.Windows.AppNotifications.AppNotificationManager
Windows.UI.Notifications.BadgeUpdateManager Microsoft.Windows.BadgeNotifications.BadgeNotificationManager
Windows.UI.Notifications.TileUpdateManager Os blocos são preteridos – use 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 aplicativos WinUI 3 empacotados, 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 do tipo hambúrguer (SplitView + NavMenuListView): Muitos exemplos de UWP implementavam a navegação usando um AppShell.xaml personalizado com SplitView e um controle NavMenuListView desenvolvido manualmente (aproximadamente mais de 500 linhas). No WinUI 3, substitua todo esse padrão pelo NavigationView, que fornece o mesmo UX com acessibilidade interna, comportamento responsivo e suporte a botão voltar. Normalmente, isso é uma redução de código de 80%.

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 código-fonte
PersonalizarINavigationService Interno Frame.Navigate + NavigationView

Dica

O pacote NuGet CommunityToolkit.Mvvm é a base MVVM recomendada para aplicativos WinUI 3. Substitui classes 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 — consulte a observação)
Application.Current.Resuming AppInstance.GetCurrent().Activated (consulte a nota)
BackgroundTaskBuilder Tarefas em Segundo Plano do SDK do Aplicativo Windows

Note

A migração do ciclo de vida do aplicativo WinUI 3 não é uma simples troca de nomes de API. O SDK do Aplicativo Windows usa um modelo de ativação e suspensão diferente. Trate o código do ciclo de vida como exigindo uma reescrita dedicada em vez de uma substituição automatizada. Consulte a documentação do ciclo de vida SDK do Aplicativo Windows para obter o modelo completo.

Configurações e armazenamento

UWP WinUI 3 (empacotado) WinUI 3 (não empacotado)
ApplicationData.Current.LocalSettings Inalterado ❌ Lançamentos – sem identidade de pacote
ApplicationData.Current.LocalFolder Inalterado ❌ Lançamentos – sem identidade de pacote
Windows.Storage.KnownFolders Inalterado ❌ Lançamentos – sem identidade de pacote

Warning

Aplicativos não empacotados não podem ser usados ApplicationData.Current – ele é lançado em runtime porque não há nenhuma identidade de pacote. Em vez disso, use APIs de arquivo de .NET padrão:

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 o seu aplicativo UWP usava DataContractSerializer com [DataMember]/[IgnoreDataMember], considere migrar para System.Text.Json (mais rápido, menor, com suporte à geração de código-fonte). O mapeamento do atributo é:

  • [DataMember][JsonPropertyName("name")] (ou apenas use os nomes de propriedade diretamente)
  • [IgnoreDataMember][JsonIgnore]
  • [DataContract] → Nenhum equivalente necessário (System.Text.Json serializa propriedades públicas por padrão)

APIs que não mudam

Windows.Devices.*, Windows.Media.*, Windows.UI.ViewManagement.UISettings, Windows.UI.Color e a maioria das APIs do WinRT fora do namespace XAML não são alteradas.

Controles sem um equivalente direto

Alguns controles UWP não existem no WinUI 3. Escolha uma substituição com base em seu cenário:

Controle UWP Substituto do WinUI 3 Notes
Pivot TabView, NavigationView (modo superior) ou RadioButtons + visibilidade Para 2–3 guias fixas, RadioButtons com alternância de visibilidade é mais simples. Para abas dinâmicas/fecháveis, use TabView.
InkToolbar (subclasse personalizada) CommandBar com AppBarToggleButton itens O recurso interno InkToolbar existe, mas os padrões personalizados de subclassificação não se adaptam bem. Recrie barras de ferramentas personalizadas usando CommandBar.
RadialController Interoperabilidade do WinRT com manipulador de janela RadialController.CreateForCurrentView() não tem equivalente direto. Usar o RadialControllerInterop com o GetForWindow(hwnd).
SystemNavigationManager Botão Voltar personalizado ou NavigationView.IsBackEnabled SystemNavigationManager.GetForCurrentView() não existe. Adicione seu próprio botão Voltar ou use o botão Voltar integrado de NavigationView.

Tinta, Win2D e impressão

Esses subsistemas exigem etapas de migração específicas além das alterações de namespace.

Tinta do Windows

As APIs InkCanvas e InkPresenter foram migradas para Microsoft.UI.Input.Inking, mas, fora isso, são idênticas. 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 exigem IRandomAccessStream. Ponte a partir de fluxos 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

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

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

Todas as Microsoft.Graphics.Canvas.* APIs (CanvasDevice, CanvasBitmap, , CanvasRenderTarget) DrawInkfuncionam da mesma maneira. Somente a referência do pacote NuGet precisa ser atualizada.

Impressão

A impressão UWP usa PrintManager.GetForCurrentView(). O WinUI 3 requer interoperação com manipulador de janela:

// 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) não são alteradas.

Importante

Se você omitir o identificador da janela, PrintManagerInterop.GetForWindow irá gerar um COMException. Esse é o mesmo padrão de interoperabilidade de FileOpenPicker — qualquer API que usava GetForCurrentView() no UWP precisa de um identificador de janela no WinUI 3.

Prompt de início

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 arquivo do projeto

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

Adicione o pacote SDK do Aplicativo Windows:

dotnet add package Microsoft.WindowsAppSDK