UWP アプリを WinUI 3 に移行する

UWP は現在、アクティブな開発を行っていません。 WinUI 3 とその後継者であるWindows アプリ SDKは、AI ツールによって移行の大部分を自動化できます。 主な課題は、AI モデルが長年の UWP サンプルでトレーニングされているため、ガイダンスなしで、離れて移動しようとしているパターンを再現することです。 このページは、エージェントが適切に対応するために必要なコンテキストを提供します。

WinUI エージェント プラグインをインストールする

winui-uwp-migration スキルは、一般的な置換を自動的に処理します。

gh copilot plugin install winui@awesome-copilot

詳細については、 WinUI エージェント プラグイン を参照してください。

API 置換テーブル

次の表は、最も一般的な API の置換をまとめたものです。 メンバー、プロパティ、あまり一般的でない API など、完全な詳細なマッピングについては、「UWP API とライブラリをWindows アプリ SDKにマッピングする」を参照してください。

Important

x:Bind は既定で OneTime モードです。 {Binding} (既定値は OneWay) とは異なり、x:Bindは、Mode=OneWayまたはMode=TwoWayを指定しない限り、1 回だけ評価されます。 移行中に、実行時に変更されるプロパティにバインドするすべての x:Bind 式を監査します。 Mode=OneWay が見つからないと、コンパイル時に表示されない "UI が更新されない" バグが発生します。

名前空間

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

スレッド化

UWP WinUI 3
CoreDispatcher DispatcherQueue
Dispatcher.RunAsync(...) DispatcherQueue.TryEnqueue(...)
CoreApplication.MainView.CoreWindow.Dispatcher this.DispatcherQueue ( Window または Pageから)

Windowing

UWP WinUI 3
ApplicationView AppWindow
ApplicationView.GetForCurrentView() AppWindow.GetFromWindowId(...)
ApplicationViewTitleBar AppWindowTitleBar
CoreWindow Microsoft.UI.Xaml.Window
SystemNavigationManager AppWindowTitleBar の戻るボタン

ダイアログとピッカー

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

Important

ピッカーでは、InitializeWithWindow(または同様のもの)を呼び出す前にPickSingleFileAsyncが必要です。

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

ContentDialog には、(XamlRootではなく) 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 タイルは非推奨です 。通知またはウィジェットを使用する

ネットワークと HTTP

UWP WinUI 3 (推奨)
Windows.Web.Http.HttpClient System.Net.Http.HttpClient (移植可能、WinRT の依存関係なし)
Windows.Web.Syndication.SyndicationClient System.ServiceModel.Syndication.SyndicationFeed + HttpClient
Windows.Web.AtomPub.AtomPubClient System.ServiceModel.Syndication またはダイレクト HTTP

Note

WinRT HTTP API (Windows.Web.Http) はパッケージ化された WinUI 3 アプリで引き続き機能しますが、移植性、デバッグの簡素化、広範なエコシステム サポート (ミドルウェア、DI、モック) には、.NET同等のものが推奨されます。

UWP WinUI 3
Frame.Navigate(typeof(MyPage)) Frame.Navigate(typeof(MyPage)) — 変更なし
SystemNavigationManager.BackRequested NavigationViewまたはAppWindowで処理します
Windows.UI.Core.Preview.SystemNavigationManagerPreview AppWindow.Closing 出来事

Note

カスタム ハンバーガー ナビゲーション (SplitView + NavMenuListView):多くの UWP サンプルでは、AppShell.xamlと手動ロール SplitView コントロール (最大 500 行) を使用したカスタム NavMenuListViewを使用してナビゲーションを実装しました。 WinUI 3 では、このパターン全体を NavigationView に置き換えます。これにより、同じ UX に組み込みのアクセシビリティ、応答性の高い動作、戻るボタンのサポートが提供されます。 これは通常、80% のコード削減です。

MVVM パターン

UWP (一般的なカスタム実装) WinUI 3 (推奨)
カスタム BindableBase / ObservableObject CommunityToolkit.Mvvm.ComponentModel.ObservableObject
カスタム DelegateCommand / RelayCommand CommunityToolkit.Mvvm.Input.RelayCommand
手動 SetProperty + OnPropertyChanged [ObservableProperty] ソース ジェネレーター
カスタム INavigationService 組み込み Frame.Navigate + NavigationView

Tip

CommunityToolkit.Mvvm NuGet パッケージは、WinUI 3 アプリに推奨される MVVM 基盤です。 これは、手動でロールされた基底クラスをテスト済みのソース生成の同等物に置き換え、数百行の定型句を排除します。

dotnet add package CommunityToolkit.Mvvm

アプリのライフサイクル

UWP WinUI 3
Application.Current.Suspending Microsoft.Windows.AppLifecycle(アーキテクチャの変更が必要 — 注記を参照)
Application.Current.Resuming AppInstance.GetCurrent().Activated (注を参照)
BackgroundTaskBuilder Windows アプリ SDKバックグラウンド タスク

Note

WinUI 3 アプリのライフサイクル移行は、単純な API 名のスワップではありません。 Windows アプリ SDKでは、別のアクティブ化モデルとサスペンション モデルが使用されます。 ライフサイクル コードは、自動置換ではなく、専用の書き換えが必要と見なされます。 完全なモデルについては、Windows アプリ SDKライフサイクルのドキュメントを参照してください。

設定とストレージ

UWP WinUI 3 (パッケージ化) WinUI 3 (パッケージ化されていない)
ApplicationData.Current.LocalSettings 変更なし ❌ スロー - パッケージ ID なし
ApplicationData.Current.LocalFolder 変更なし ❌ スロー - パッケージ ID なし
Windows.Storage.KnownFolders 変更なし ❌ スロー - パッケージ ID なし

Warning

パッケージ化されていないアプリApplicationData.Current を使用できません。パッケージ ID がないため、実行時にスローされます。 代わりに、標準.NET ファイル API を使用します。

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

UWP アプリがDataContractSerializer[DataMember]/で[IgnoreDataMember]使用している場合は、System.Text.Jsonに移行することを検討してください (高速、小規模、ソース世代のサポート)。 属性マッピングは次のとおりです。

  • [DataMember][JsonPropertyName("name")] (またはプロパティ名を直接使用する)
  • [IgnoreDataMember][JsonIgnore]
  • [DataContract] → 同等の必要はありません (System.Text.Json は既定でパブリック プロパティをシリアル化します)

変更されない API

Windows.Devices.*Windows.Media.*Windows.UI.ViewManagement.UISettingsWindows.UI.Color、および XAML 名前空間外のほとんどの WinRT API は変更されません。

直接対応するコントロールがないもの

一部の UWP コントロールは WinUI 3 に存在しません。 シナリオに基づいて置換を選択します。

UWP コントロール WinUI 3 の置換 注記
Pivot TabViewNavigationView (トップ モード)、または RadioButtons + 可視性 2 ~ 3 個の固定タブの場合、可視性切り替えによる RadioButtons は最も簡単です。 動的/閉じ可能なタブには、 TabViewを使用します。
InkToolbar (カスタム サブクラス) CommandBar AppBarToggleButton項目を含む 組み込みの InkToolbar は存在しますが、カスタム サブクラス化パターンは正常に変換されません。 CommandBarを使用してカスタム ツール バーを再構築します。
RadialController ウィンドウ ハンドルを使用した WinRT 相互運用 RadialController.CreateForCurrentView() は直接同等の値を持っていません。 RadialControllerInteropGetForWindow(hwnd) と共に使用する。
SystemNavigationManager カスタム戻るボタンまたは NavigationView.IsBackEnabled SystemNavigationManager.GetForCurrentView() が存在しません。 独自の戻るボタンを追加するか、 NavigationViewの組み込みの戻るボタンを使用します。

インク、Win2D、印刷

これらのサブシステムには、名前空間の変更以外の特定の移行手順が必要です。

Windows インク

InkCanvas API と InkPresenter API はMicrosoft.UI.Input.Inkingに移行しますが、それ以外の場合は同じです。 明白ではない変更の 1 つは CoreInputDeviceTypesです。

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

InkStrokeContainer.SaveAsync() LoadAsync()には引き続きIRandomAccessStreamが必要です。 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

Win2D パッケージ名は変更されましたが、API サーフェスは同じです。

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

すべての Microsoft.Graphics.Canvas.* API (CanvasDeviceCanvasBitmapCanvasRenderTargetDrawInk) は同じように動作します。 更新が必要なのは、NuGet パッケージ参照のみです。

印刷

UWP 印刷では、 PrintManager.GetForCurrentView()が使用されます。 WinUI 3 には、ウィンドウ ハンドル相互運用機能が必要です。

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

PrintDocumentレンダリング API (PaginateGetPreviewPageAddPages) は変更されません。

Important

ウィンドウ ハンドルを省略すると、 PrintManagerInterop.GetForWindowCOMException をスローします。 これは、 FileOpenPicker と同じ相互運用パターンです。UWP で GetForCurrentView() を使用するすべての API には、WinUI 3 のウィンドウ ハンドルが必要です。

スタート プロンプト

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.

Project ファイルの変更

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>

Windows アプリ SDK パッケージを追加します。

dotnet add package Microsoft.WindowsAppSDK