本文へスキップ
ysk-hack-log
戻る

WPFからWinUI 3への移行の勘所|つまずく差分を一枚のマップで整理

「WPFからWinUI 3への移行の勘所|つまずく差分を一枚のマップで整理」の記事アイキャッチ

「既存のWPFアプリをWinUI 3に移したい」——そう考えて手を動かすと、すぐに気づきます。単純にコピペしてもまず動きません。 私も同じ道を通り、名前空間・コントロール・スレッド…と、あちこちで細かく詰まりました。

この記事では、WPFからWinUI 3へ移行するときにどこが変わり、どこでつまずくのかを、一枚のマップとして整理します。細かな書き換え手順よりも、「まず全体像を押さえて心の準備をする」ことを目的にした概要です。WinUIの基礎は入門記事、MVVM周りはMVVM入門も参照してください。

Table of contents

Open Table of contents

大前提:単純移植は向かない

最初に結論から言うと、WPFアプリの「そのまま載せ替え」は基本的に効きません。 名前空間もコントロールも作法も違うため、実態は「移行」というより部分的な作り直しに近くなります。

そのため、既存の安定したWPFアプリを無理に移すより、新規開発でWinUIを選ぶ方が向いています(この判断は入門記事でも触れています)。それでも移行したい場合に、差分の地図を持っておくと迷いが減ります。

1. 名前空間の置き換え

まず大量に出るのが名前空間の違いです。WPFの System.Windows.* は、WinUIでは Microsoft.UI.Xaml.* に変わります。

WPFWinUI 3
System.WindowsMicrosoft.UI.Xaml
System.Windows.ControlsMicrosoft.UI.Xaml.Controls
System.Windows.MediaMicrosoft.UI.Xaml.Media

using の一括置換である程度は進みますが、クラスによっては移動先が異なるものもあり、機械的な置換だけでは終わりません。

2. コントロールの置き換え

WPFにあってWinUIに「そのままの名前では」存在しないコントロールがあります。代表的な対応は次のとおりです。

WPFWinUI 3での代替
DataGrid標準には無し → ListView で代替。表形式が必要なら Community Toolkit の DataGrid や WinUI.TableView(コミュニティ製)を検討
WrapPanelCommunity Toolkit の WrapPanel(同名で素直に置き換え可)。大量要素を仮想化したいなら ItemsRepeater + WrapLayout
TabControlTabView
Menu / ToolBarMenuBar / CommandBar

「同じ名前がない=作り直し」ではなく、役割の近いモダンなコントロールに置き換えるイメージです。Community Toolkit が代替の受け皿になることも多いです。

3. スレッド:Dispatcher → DispatcherQueue

UIスレッド外から画面を更新する定番の Dispatcher は、WinUIでは DispatcherQueue に変わります。

// WPF
Dispatcher.Invoke(() => { /* UI更新 */ });

// WinUI 3
DispatcherQueue.TryEnqueue(() => { /* UI更新 */ });

非同期処理からUIを触るコードは各所にあるはずなので、ここは確実に書き換えが必要です。

4. リソースとテーマ:DynamicResource → ThemeResource

WPFでテーマ切り替えなどに使った DynamicResource は、WinUIにはありません。 代わりに、テーマ(ライト/ダーク)に追従するリソースは ThemeResource を使います。

<!-- WPF -->
<TextBlock Foreground="{DynamicResource MyBrush}" />

<!-- WinUI 3 -->
<TextBlock Foreground="{ThemeResource MyBrush}" />

固定値でよければ StaticResource はそのまま使えます。テーマ対応が絡む箇所だけ ThemeResource に読み替えるのがポイントです。

5. スタイルのトリガー:Trigger → Behaviors / VisualStateManager

WPFの Style 内の Trigger(DataTrigger / MultiTrigger など、状態に応じた見た目の切り替え)は、WinUIにはありません。置き換え先は、用途によって2つに分かれます。

いずれも「トリガーをそのまま移す」のではなく、考え方から組み替える箇所です。

6. バインディング:Binding → x:Bind

WPFの {Binding}(DataContext 起点・実行時解決)に対し、WinUIでは型安全で高速な {x:Bind}(ページの分離コード起点・コンパイル時解決) が推奨です。既定モードも OneWay → OneTime と変わります。

この差分はMVVMの組み方に直結するため、詳しくはMVVM入門記事の「WPFのMVVMとの違い」で解説しています。従来型の {Binding} もWinUIで使えますが、移行を機に x:Bind へ寄せるのがおすすめです。

7. 画像:BitmapImage の名前空間が変わる

WPFで画面表示に使う BitmapImage は System.Windows.Media.Imaging にありますが、WinUIでは Microsoft.UI.Xaml.Media.Imaging.BitmapImage に変わります。多くの場合、移行はまずこの名前空間の読み替えが中心です。

加えて、System.Drawing.Bitmap などGDI+系のAPI(どちらかというとWinForms寄り)を画像処理で使っていた場合は、XAML表示とは相性が悪いため、そこも見直しが必要になります。

まとめ

WPFからWinUI 3への移行は、「差分を知っていれば怖くないが、知らないと各所で足を止められる」作業です。主なマップは次のとおり。

  1. 名前空間 … System.Windows → Microsoft.UI.Xaml
  2. コントロール … DataGrid/WrapPanel/TabControl などを近いものに置換
  3. スレッド … Dispatcher → DispatcherQueue
  4. リソース/テーマ … DynamicResource → ThemeResource
  5. トリガー … Trigger → Behaviors(Community Toolkit)/VisualStateManager
  6. バインディング … {Binding} → {x:Bind}
  7. 画像 … BitmapImage の名前空間変更(System.Windows.Media.Imaging → Microsoft.UI.Xaml.Media.Imaging)

繰り返しになりますが、実態は部分的な作り直しです。小さな画面から一つずつ置き換え、都度動かして確認していくのが、遠回りに見えて一番の近道でした。


この記事をシェア:

前の記事
WinUIでMVVMをはじめる|CommunityToolkit.Mvvmで「画面とロジックの分離」を最小コードで
次の記事
WinUIのプロトコルアクティベーション入門|独自URI(myapp://)でアプリを起動する