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.UISettings、Windows.UI.Color、および XAML 名前空間外のほとんどの WinRT API は変更されません。

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

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

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

インク、Win2D、印刷

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

Windows インク

WinUI には、Windows アプリ SDKの試験的なリリースの実験用 API としてInkCanvas、InkToolbar、およびInkPresenterが含まれています。 安定版リリースには含まれません。 セットアップ、ツール バーのカスタマイズ、既知の制限事項については、「 WinUI アプリの Inking コントロール」を参照してください。

試験段階のリリースでは、インク入力を処理するコントロールと型は Microsoft.UI.Xaml.Controls にあります。 ストロークと描画属性は、 Windows.UI.Input.Inkingに残ります。

UWP WinUI 3 (実験的リリース)
Windows.UI.Xaml.Controls.InkCanvas、 InkToolbar、およびその他の InkToolbar* 型 Microsoft.UI.Xaml.Controls、同じ型名。 一部のメンバーは異なります。
Windows.UI.Input.Inking.InkPresenter、InkStrokeContainer、InkStrokeInput、InkUnprocessedInput、InkSynchronizer、InkInputConfiguration、InkInputProcessingConfiguration、InkInputProcessingMode、InkInputRightDragAction、InkHighContrastAdjustment、InkStrokesCollectedEventArgs、InkStrokesErasedEventArgs Microsoft.UI.Xaml.Controls、同一の型名。 一部のメンバーは異なります。
Windows.UI.Input.Inking.InkStroke、 InkDrawingAttributes、 InkPoint、 InkStrokeBuilder、 InkPersistenceFormat、 PenTipShape 変更なし
Windows.UI.Core.CoreInputDeviceTypes 変更なし

最初の 2 つの行のすべての UWP 型には同じ名前の対応する型がありますが、Windows アプリ SDK 2.5.4-experimental にはそれらのメンバーのすべてが含まれているわけではありません。

  • InkStrokeContainer にはパブリック コンストラクターがなく、 InkPresenter.StrokeContainer は読み取り専用です。 ストロークのセットを切り替えるには、各セットを SaveAsync で保存し、LoadAsync で復元します。これは現在のストロークを置き換えます。
  • SaveAsyncとLoadAsyncはIAsyncActionを返すため、進行状況は報告されません。また、SaveAsyncは書き込んだバイト数を返しません。
  • InkStrokeContainer.GetRecognitionResults、 InkStrokeContainer.UpdateRecognitionResults、および InkInputConfiguration.IsPenHapticFeedbackEnabled は使用できません。
  • InkToolbarRulerButton.Ruler と InkToolbar.IsRulerButtonCheckedChanged イベントは使用できません。 UWP では InkToolbarStencilButton は非推奨になり、代わりに InkToolbarRulerButton が推奨されるため、代わりにステンシル ボタンと InkToolbar.IsStencilButtonCheckedChanged イベントを使用してください。

Windows アプリ SDK 2.4.1-experimental では、InkToolbarEraserKind や InkToolbarEraserButton.SelectedEraser などの消しゴム API が追加されましたが、これらは 2.5.4-experimental で削除されました。 これらは UWP の一部だったことは一度もないため、移行されたコードに追加しないでください。 完全な一覧については、「 2.4.1-experimental からの変更」を参照してください。

InkPresenterやInkStrokeContainerなどの型は両方の名前空間に存在するため、Microsoft.UI.Xaml.ControlsとWindows.UI.Input.Inkingの両方をインポートすると、これらの名前を使用するとエラー CS0104 が発生します。 Microsoft.UI.Xaml.Controlsをインポートし、使用するWindows.UI.Input.Inking型のエイリアス ディレクティブを追加します。

using Microsoft.UI.Xaml.Controls;
using InkDrawingAttributes = Windows.UI.Input.Inking.InkDrawingAttributes;
using InkStroke = Windows.UI.Input.Inking.InkStroke;

InkStrokeContainer.SaveAsyncはIOutputStreamに書き込み、IInputStreamはLoadAsyncから読み取ります。 System.IOファイル ストリームを使用するには、AsOutputStreamとAsInputStreamに変換します。 ファイルには、これらのWindows ランタイムメソッドを await するための using System.IO; が、using Windows.Storage.Streams; および using System; と併せて必要です。

// Save ink strokes to a file.
using (FileStream fileStream = File.Create(filePath))
using (IOutputStream output = fileStream.AsOutputStream())
{
    await inkStrokeContainer.SaveAsync(output);
    await output.FlushAsync();
}

// Load ink strokes from a file.
using (FileStream fileStream = File.OpenRead(filePath))
using (IInputStream input = fileStream.AsInputStream())
{
    await inkStrokeContainer.LoadAsync(input);
}

InkToolbar.TargetInkCanvasを使用してツール バーをキャンバスに接続し続けたり、TargetInkPresenterを設定して、ツール バーをInkPresenterに直接接続したりできます。 ツール バーに独自のツールを追加するには、インク ツール バーのカスタマイズ に示すように、InkToolbarCustomToolButton と InkToolbarCustomToggleButton を使用します。 移行する前に、ルーラーと分度器ステンシルに関して報告された問題など、既知の制限事項を確認してください。

アプリで安定版を使用する必要がある場合、移行先の組み込みの手描き入力コントロールはありません。 Win2D でストロークをレンダリングし、ポインター入力を自分で処理するか、サード パーティ製の手描き入力ライブラリを使用します。 InkToolbarを置き換えるには、CommandBar 項目を含む AppBarToggleButton を使用します。

Win2D

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

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

すべての Microsoft.Graphics.Canvas.* API (CanvasDevice、 CanvasBitmap、 CanvasRenderTarget、 DrawInk) は同じように動作します。 更新が必要なのは、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 (Paginate、GetPreviewPage、AddPages) は変更されません。

Important

ウィンドウ ハンドルを省略すると、 PrintManagerInterop.GetForWindow は COMException をスローします。 これは、 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)
- InkCanvas, InkToolbar, InkPresenter, InkStrokeContainer, and the other ink input types → Microsoft.UI.Xaml.Controls (experimental Windows App SDK releases only; if the project uses a stable release, flag them instead)
- Ink members that Windows App SDK 2.5.4-experimental doesn't include (new InkStrokeContainer(), assignments to InkPresenter.StrokeContainer, GetRecognitionResults, UpdateRecognitionResults, IsPenHapticFeedbackEnabled, InkToolbarRulerButton.Ruler, IsRulerButtonCheckedChanged, and progress or byte counts from SaveAsync and LoadAsync) → flag them
- PrintManager.GetForCurrentView → PrintManagerInterop.GetForWindow(hwnd)
- Win2D.uwp NuGet → Microsoft.Graphics.Win2D NuGet
- InkStroke, InkDrawingAttributes, InkPoint, InkStrokeBuilder → no change (Windows.UI.Input.Inking; use using aliases to avoid CS0104)

Do not use any Windows.UI.Xaml.* namespaces in new code.
Do not use CoreDispatcher — use DispatcherQueue.
Do not add InkToolbarEraserKind, SelectedEraser, or other eraser APIs from Windows App SDK 2.4.1-experimental. Version 2.5.4-experimental removed them.
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