winui3-migration-guide について
winui3-migration-guideは、UWPアプリをWinUI 3へ移行する開発者や、生成コードのAPIを確認する開発者向けのスキルです。UI、ウィンドウ、スレッド、テストの対応表や修正例、チェックリストを提供します。
主な機能
- 01UWPの名前空間とAPIをWinUI 3に対応付け
- 02ダイアログとディスパッチャーの一般的な修正
- 03ウィンドウ、ピッカー、スレッド処理の更新
- 04バックグラウンドタスクと設定の移行案内
- 05プロジェクトとテスト変更のチェックリスト
活用シーン
- 01UWPアプリのWinUI 3への移行
- 02生成コードに残る旧UWP APIの確認
- 03ウィンドウとファイルピッカーの置き換え
- 04WinUI 3向けテストの更新
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ github/ awesome-copilot --skill winui3-migration-guideインストール後、Claude Code で/winui3-migration-guideを入力して読み込まれたか確認します。
詳細
WinUI 3 移行ガイド
UWP アプリを WinUI 3/Windows App SDK に移行する場合や、生成されたコードがレガシーな UWP パターンではなく、正しい WinUI 3 API を使用しているか確認する場合に、このスキルを使用します。
名前空間の変更
すべての Windows.UI.Xaml.* 名前空間は Microsoft.UI.Xaml.* に移行します。
| 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.Xaml.Input | Microsoft.UI.Xaml.Input |
Windows.UI.Xaml.Data | Microsoft.UI.Xaml.Data |
Windows.UI.Xaml.Navigation | Microsoft.UI.Xaml.Navigation |
Windows.UI.Xaml.Shapes | Microsoft.UI.Xaml.Shapes |
Windows.UI.Composition | Microsoft.UI.Composition |
Windows.UI.Input | Microsoft.UI.Input |
Windows.UI.Colors | Microsoft.UI.Colors |
Windows.UI.Text | Microsoft.UI.Text |
Windows.UI.Core | Microsoft.UI.Dispatching(ディスパッチャー用) |
Copilot で最もよくあるミス 3 選
1. XamlRoot を指定しない ContentDialog
// ❌ WRONG — Throws InvalidOperationException in WinUI 3
var dialog = new ContentDialog
{
Title = "Error",
Content = "Something went wrong.",
CloseButtonText = "OK"
};
await dialog.ShowAsync();
// ✅ CORRECT — Set XamlRoot before showing
var dialog = new ContentDialog
{
Title = "Error",
Content = "Something went wrong.",
CloseButtonText = "OK",
XamlRoot = this.Content.XamlRoot // Required in WinUI 3
};
await dialog.ShowAsync();
2. ContentDialog ではなく MessageDialog を使用する
// ❌ WRONG — UWP API, not available in WinUI 3 desktop
var dialog = new Windows.UI.Popups.MessageDialog("Are you sure?", "Confirm");
await dialog.ShowAsync();
// ✅ CORRECT — Use ContentDialog
var dialog = new ContentDialog
{
Title = "Confirm",
Content = "Are you sure?",
PrimaryButtonText = "Yes",
CloseButtonText = "No",
XamlRoot = this.Content.XamlRoot
};
var result = await dialog.ShowAsync();
if (result == ContentDialogResult.Primary)
{
// User confirmed
}
3. DispatcherQueue ではなく CoreDispatcher を使用する
// ❌ WRONG — CoreDispatcher does not exist in WinUI 3
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
StatusText.Text = "Done";
});
// ✅ CORRECT — Use DispatcherQueue
DispatcherQueue.TryEnqueue(() =>
{
StatusText.Text = "Done";
});
// With priority:
DispatcherQueue.TryEnqueue(DispatcherQueuePriority.High, () =>
{
ProgressBar.Value = 100;
});
ウィンドウ管理の移行
ウィンドウ参照
// ❌ WRONG — Window.Current does not exist in WinUI 3
var currentWindow = Window.Current;
// ✅ CORRECT — Use a static property in App
public partial class App : Application
{
public static Window MainWindow { get; private set; }
protected override void OnLaunched(LaunchActivatedEventArgs args)
{
MainWindow = new MainWindow();
MainWindow.Activate();
}
}
// Access anywhere: App.MainWindow
ウィンドウ管理
| UWP API | WinUI 3 API |
|---|---|
ApplicationView.TryResizeView() | AppWindow.Resize() |
AppWindow.TryCreateAsync() | AppWindow.Create() |
AppWindow.TryShowAsync() | AppWindow.Show() |
AppWindow.TryConsolidateAsync() | AppWindow.Destroy() |
AppWindow.RequestMoveXxx() | AppWindow.Move() |
AppWindow.GetPlacement() | AppWindow.Position プロパティ |
AppWindow.RequestPresentation() | AppWindow.SetPresenter() |
タイトルバー
| UWP API | WinUI 3 API |
|---|---|
CoreApplicationViewTitleBar | AppWindowTitleBar |
CoreApplicationView.TitleBar.ExtendViewIntoTitleBar | AppWindow.TitleBar.ExtendsContentIntoTitleBar |
ダイアログとピッカーの移行
ファイル/フォルダーのピッカー
// ❌ WRONG — UWP style, no window handle
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".txt");
var file = await picker.PickSingleFileAsync();
// ✅ CORRECT — Initialize with window handle
var picker = new FileOpenPicker();
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
WinRT.Interop.InitializeWithWindow.Initialize(picker, hwnd);
picker.FileTypeFilter.Add(".txt");
var file = await picker.PickSingleFileAsync();
スレッド処理の移行
| UWP パターン | WinUI 3 相当 |
|---|---|
CoreDispatcher.RunAsync(priority, callback) | DispatcherQueue.TryEnqueue(priority, callback) |
Dispatcher.HasThreadAccess | DispatcherQueue.HasThreadAccess |
CoreDispatcher.ProcessEvents() | 相当する API はありません — 非同期コードを再構成してください |
CoreWindow.GetForCurrentThread() | 利用できません — DispatcherQueue.GetForCurrentThread() を使用してください |
主な違い:UWP は ASTA(アプリケーション STA)を使用し、組み込みの再入防止機能を備えています。WinUI 3 はこの保護機能のない標準 STA を使用します。非同期コードがメッセージを処理する際は、再入の問題に注意してください。
バックグラウンドタスクの移行
// ❌ WRONG — UWP IBackgroundTask
public sealed class MyTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance) { }
}
// ✅ CORRECT — Windows App SDK AppLifecycle
using Microsoft.Windows.AppLifecycle;
// Register for activation
var args = AppInstance.GetCurrent().GetActivatedEventArgs();
if (args.Kind == ExtendedActivationKind.AppNotification)
{
// Handle background activation
}
アプリ設定の移行
| シナリオ | パッケージ化されたアプリ | パッケージ化されていないアプリ |
|---|---|---|
| シンプルな設定 | ApplicationData.Current.LocalSettings | LocalApplicationData 内の JSON ファイル |
| ローカルファイルストレージ | ApplicationData.Current.LocalFolder | Environment.GetFolderPath(SpecialFolder.LocalApplicationData) |
GetForCurrentView() の置き換え
GetForCurrentView() を使用するすべてのパターンは、WinUI 3 デスクトップアプリでは利用できません。
| UWP API | WinUI 3 での置き換え |
|---|---|
UIViewSettings.GetForCurrentView() | AppWindow のプロパティを使用 |
ApplicationView.GetForCurrentView() | AppWindow.GetFromWindowId(windowId) |
DisplayInformation.GetForCurrentView() | Win32 の GetDpiForWindow() または XamlRoot.RasterizationScale |
CoreApplication.GetCurrentView() | 利用できません — ウィンドウを手動で追跡してください |
SystemNavigationManager.GetForCurrentView() | NavigationView で戻るナビゲーションを直接処理してください |
テストの移行
UWP 単体テストプロジェクトは WinUI 3 では動作しません。WinUI 3 テストプロジェクトテンプレートへ移行する必要があります。
| UWP | WinUI 3 |
|---|---|
| 単体テストアプリ (Universal Windows) | 単体テストアプリ (WinUI in Desktop) |
| UWP 型を含む標準の MSTest プロジェクト | Xaml ランタイムには WinUI テストアプリを使用する必要があります |
すべてのテストに [TestMethod] | ロジックには [TestMethod]、XAML/UI テストには [UITestMethod] |
| クラスライブラリ (Universal Windows) | クラスライブラリ (WinUI in Desktop) |
// ✅ WinUI 3 unit test — use [UITestMethod] for any XAML interaction
[UITestMethod]
public void TestMyControl()
{
var control = new MyLibrary.MyUserControl();
Assert.AreEqual(expected, control.MyProperty);
}
ポイント: [UITestMethod] 属性は、XAML UI スレッドでテストを実行するようテストランナーに指示します。これは、あらゆる Microsoft.UI.Xaml 型をインスタンス化するために必要です。
移行チェックリスト
- すべての
Windows.UI.Xaml.*using ディレクティブをMicrosoft.UI.Xaml.*に置き換える -
Windows.UI.ColorsをMicrosoft.UI.Colorsに置き換える -
CoreDispatcher.RunAsyncをDispatcherQueue.TryEnqueueに置き換える -
Window.CurrentをApp.MainWindow静的プロパティに置き換える - すべての
ContentDialogインスタンスにXamlRootを追加する - すべてのピッカーを
InitializeWithWindow.Initialize(picker, hwnd)で初期化する -
MessageDialogをContentDialogに置き換える -
ApplicationView/CoreWindowをAppWindowに置き換える -
CoreApplicationViewTitleBarをAppWindowTitleBarに置き換える - すべての
GetForCurrentView()呼び出しをAppWindowの同等のものに置き換える - Share および Print マネージャーの相互運用を更新する
-
IBackgroundTaskをAppLifecycleアクティベーションに置き換える - プロジェクトファイルを更新する: TFM を
net10.0-windows10.0.22621.0にし、<UseWinUI>true</UseWinUI>を追加する - 単体テストを 単体テストアプリ (WinUI in Desktop) プロジェクトへ移行する。XAML テストには
[UITestMethod]を使用する - パッケージ化構成と非パッケージ化構成の両方でテストする
コメント
Markdown 対応