WinForms/WPF/WinUI 的選法 - 實務判斷表

· 更新日期: · · WinForms, WPF, WinUI, C#, Windows 開發, UI 設計

更新紀錄(2 筆,最後更新 2026年09月04日)

本文的修改紀錄。已保存的更新前版本,可透過附有 DOI 的永久連結閱讀。

已將繁體中文版改寫為日文原文的完整翻譯。先前的繁體中文版只譯出日文原文的一部分,遺漏了章節、表格、Mermaid 圖、圖說與 FAQ。本次依日文原文將這些內容全部補回,並新增本文的知識地圖章節。技術主張與日文版一致。 查看更新前的版本 (DOI: 10.5281/zenodo.22279454)
補上了日文原文中已有的諮詢引導(consultation_services)。內文沒有改動。 查看更新前的版本 (DOI: 10.5281/zenodo.21616327)
初次發布
引用本文(DOI: 10.5281/zenodo.21616326)

本文保存於 Zenodo。以下同時提供一律指向最新版本的 DOI,以及固定於您正在閱讀版本的 DOI。

Go Komura(2026)。〈WinForms/WPF/WinUI 的選法 - 實務判斷表〉。小村軟體有限公司。https://doi.org/10.5281/zenodo.21616326 https://comcomponent.com/zh-TW/blog/2026/03/18/001-winforms-wpf-winui-decision-table/

DOI(最新版本)
10.5281/zenodo.21616326
DOI(此版本)
10.5281/zenodo.22297164

目標讀者:用 C# / .NET 開發 Windows 桌面應用程式的工程師,以及負責決定技術選型的人。 前提:使用現行的 .NET(不是 .NET Framework),目標平台只有 Windows。 閱讀方式:只要結論就讀第 1 章和第 3 章;想決定既有應用程式的延續使用方針就從第 7 章開始;想要最後的決定關鍵就從第 8 章開始。

用 C# / .NET 開發 Windows 桌面應用程式時, 每次都不起眼卻很麻煩的,就是 WinForms、WPF、WinUI 要選哪一個

這裡危險的是,

  • 因為最新所以選 WinUI
  • 因為最熟悉所以選 WinForms
  • 因為感覺介於中間所以選 WPF

這類模糊的選法。

模糊選法的風險顯示「因為最新所以選WinUI、因為最熟悉所以選WinForms、因為感覺介於中間所以選WPF」這種模糊的選法很危險,實務上要用更明確的軸線來看的圖。因為最新所以選WinUI模糊的選法因為最熟悉所以選WinForms因為感覺介於中間所以選WPF實務上要用明確的軸線來看

圖 1: 不是靠「最新、最熟悉、感覺介於中間」,而是用明確的軸線來選。

在實務上,該看的軸線要更清楚一些。

  • 是新專案開發,還是既有資產的延伸
  • 畫面是以輸入表單為主,還是需要表現力
  • Windows 風格的現代 UI 本身是不是產品價值
  • 散發、更新、企業內維運要怎麼處理
  • 開發風格是以 Windows Forms Designer 為中心,還是以 XAML/MVVM 為中心

本文把這些整理成一張判斷表。 另外,本文所說的 WinUI 主要是指 WinUI 3 + Windows App SDK12

還有,這 3 個 全部都是 Windows 專用。 如果 macOS / Linux 也在視野內,那問題設定本身就不一樣了。341

3個都是Windows專用顯示WinForms、WPF、WinUI都是Windows專用,如果macOS或Linux也在視野內,問題設定本身就不同的圖。WinForms全部都是 Windows 專用WPFWinUImacOS / Linux也在視野內就是另一個問題設定

圖 2: 3 個都是 Windows 專用,要跨平台就變成另一個問題設定。

1. 先講結論(一句話)

先用相當粗略、但實務上好用的說法來講,是這樣。

  • 既有 WinForms 應用程式 很大的話,先以 繼續用 WinForms 為基本方向來看
  • 既有 WPF 應用程式 很大的話,先以 繼續用 WPF 為基本方向來看
  • 新開發的小~中規模公司內部工具,以標準控制項為主、以輸入畫面為主、想快點做出來的話,WinForms 現在依然相當強35
  • 新開發的中~大規模業務應用程式,畫面數量多,而且想好好使用資料繫結、樣式、樣板、命令、MVVM 的話,多半是 WPF 最不容易出問題467
  • 新開發的 Windows 專用產品,如果現代的 Windows UI、Fluent、最新的 Windows 體驗直接構成產品價值,WinUI 就很有力12
  • 只是 想使用最新的 Windows API 的話,不一定要 WinUI。WPF / WinForms 一樣可以納入 Windows App SDK 的功能28910
  • 「之後再一點一點把 WinUI 插進去就好」 為前提來選,有點危險。階段性遷移這件事,比想像中更容易陷入泥沼1011

簡單說,大致上就是這幾件事。

  1. 既有資產很大的話,先保住那個系譜
  2. 新專案要快速做出標準表單,就選 WinForms
  3. 新專案是會長期成長的 Windows 業務應用程式,就選 WPF
  4. 新專案的需求本身就是現代 Windows UI,就選 WinUI
  5. 只是想用 Windows App SDK,就不要一口氣全部換成 WinUI

框架選型既是 UI 技術的選型,同時也是 散發、維運、學習成本、遷移成本的選型。 這裡如果只用「新/舊」來決定,後續的散發設計與維護成本會回過頭來反噬。

先講結論的決定方式顯示既有資產很大就先保住那個系譜,新專案要快速做標準表單選WinForms,長期成長的Windows業務應用程式選WPF,需求本身就是現代Windows UI就選WinUI的決定方式的圖。否,是新專案既有資產是否很大先保住那個系譜是否以標準表單為主WinForms現代UI本身是不是需求WPF,長期成長的業務應用程式WinUI只為了SDK就不要全面改成WinUI

圖 3: 依既有資產、畫面性質、現代 UI 需求的順序來看,結論大致就定了。

圖中實線表示始終成立的關係,虛線表示附帶條件的關係(成立條件寫在詳細頁面中各關係的說明中)。關係的完整清單(共 24 條,附依據與可信度)以及主要概念的定義,彙整在知識地圖詳細頁面(日文)。資料:JSON-LD / Turtle

2. 本文所說的 3 種技術

先把用語對齊一下。後面會一直出現的縮寫,在這裡先寫出全稱。

用語 全稱 大致上是什麼
XAML eXtensible Application Markup Language 用宣告式方式描述畫面結構的 XML 式標記語言。WPF 和 WinUI 都使用它
Designer Windows Forms Designer 在 Visual Studio 上拖曳控制項來組畫面的功能。產生的結果會以 *.Designer.cs 這個程式碼檔案留下來
Data Binding 資料繫結 把畫面的屬性與資料端的屬性連起來,其中一邊變動時另一邊也跟著變的機制
MVVM Model-View-ViewModel 分成畫面 (View)、畫面用的狀態與命令 (ViewModel)、業務邏輯與資料 (Model) 的設計模式。View 與 ViewModel 之間用 Data Binding 連接
Fluent Fluent Design System Microsoft 為 Windows 11 的外觀與操作感所訂的設計體系。WinUI 以它為前提
Windows App SDK 包含 WinUI 在內、現在給 Windows 用的開發程式庫集合。也有 UI 以外的功能,而且可以加到 WPF / WinForms / Win32 的既有應用程式上
XAML Islands 只在既有 WPF / WinForms / Win32 應用程式的一部分嵌入新版 XAML 控制項的機制。細節在 5.3.3 說明
MSIX Windows 的應用程式套件格式。安裝、更新、解除安裝都可以交給 OS 端的機制處理
package identity 套件 ID Windows 能辨識該處理程序屬於哪一個應用程式套件的狀態。通知、關聯等一部分 Windows 功能沒有它就不能用
技術 大致上是什麼 強項的軸線
WinForms 用 Visual Studio 的 Designer 就能快速組出表單的傳統 .NET Windows 桌面 UI 快速做畫面、標準控制項、活用既有資產
WPF 用 XAML、資料繫結、樣式、樣板、命令做出有表現力 UI 的 Windows 專用 UI 中~大規模業務應用程式、MVVM、畫面容易整理
WinUI 建立在 Windows App SDK 上的現代 Windows 原生 UI Fluent、最新 Windows 體驗、高 DPI、現代的產品 UI

WinForms 在 Microsoft Learn 上,也被說明成 具備控制項、圖形、資料繫結、使用者輸入,並且能用 Visual Studio 的拖放式 Designer 輕鬆做出應用程式 的框架。3

WPF 則是包含 解析度無關的向量繪製XAML資料繫結樣式/樣板2D / 3D動畫 在內,表現力很高的 UI 框架。4

WinUI 是 Windows App SDK 的一部分,以 高 DPI、現代的輸入、流暢的動畫、Fluent 系的體驗 為前提,是現在給 Windows 用的 UI 框架。12 另外,data binding / MVVM 的路徑它也一樣具備。12

這裡重要的是,Windows App SDK 和 WinUI 並不是同一件事。 WinUI 是 Windows App SDK 的 UI 框架部分,但 Windows App SDK 本身 也可以加到 WPF / WinForms / Win32 的既有應用程式上210

所以,

  • 使用 WinUI
  • 使用 Windows App SDK 的功能

看起來很像,其實是不同的判斷。 如果這兩件事混在一起討論,「要不要遷移 UI」和「要不要加功能」就會被當成同一個題目,結論很難收斂。

Windows App SDK和WinUI不是同一件事顯示WinUI是Windows App SDK的UI框架部分,而Windows App SDK本身也可以加到WPF、WinForms、Win32的既有應用程式上,因此「使用WinUI」的判斷與「使用SDK功能」的判斷是兩回事的圖。Windows App SDKWinUI,也就是其UI框架部分也能加到 WPF / WinForms / Win32「使用WinUI」的判斷「使用SDK功能」的判斷看似相近其實是不同的判斷

圖 4: 「使用 WinUI」和「使用 Windows App SDK 的功能」是不同的判斷。

3. 一張表看完的判斷表

先放上實務中最好用的一張表。

情境 先選什麼 理由
既有 WinForms 應用程式的改版、延續使用、升級到 .NET 繼續用 WinForms 既有畫面、Designer 資產、控制項資產都容易沿用
既有 WPF 應用程式的改版、延續使用、升級到 .NET 繼續用 WPF XAML、Binding、MVVM、畫面結構都可以直接沿用
新專案、公司內部工具、設定畫面、管理畫面、以輸入表單為主 WinForms 以標準控制項為主的話,起步很快
新專案、畫面數量多、狀態複雜、想用樣式/樣板/MVVM WPF 畫面的職責切分與 UI 整理都比較容易
新專案、Windows 風格的現代 UI 本身就是需求 WinUI 容易貼近 Fluent 與最新的 Windows 體驗
維持既有 WPF / WinForms,但想用 Toast / Windowing / App Lifecycle 等 現行框架 + Windows App SDK 為了最新的 Windows 功能,多半不需要做到 UI 全面遷移
對 COM / ActiveX / 老舊第三方控制項的相依很重 偏向既有框架 UI 之前,相依性的遷移成本就已經很大
強烈受到散發、更新、企業內維運的條件限制 優先考慮 WPF / WinForms,選 WinUI 就要提早確認散發設計 WinUI 必須提早檢視 Windows App SDK / packaging 這一類前提
將來想跨平台 連這 3 個以外的選項一起重新評估 這 3 個全部都是 Windows 專用

光是這張表大致就夠用了,但還會剩下 2 個容易讓人猶豫的點。

  1. 新開發的 Windows 業務應用程式,要靠向 WinForms 還是 WPF
  2. 已經有既有 WPF / WinForms,還要不要走向 WinUI

這 2 點看著後面的比較表來想,會比較容易判斷。

判斷表之後剩下的2個煩惱顯示光靠一張判斷表,還會剩下新開發的Windows業務應用程式要選WinForms還是WPF,以及已經有既有WPF或WinForms還要不要走向WinUI這2點,要用後面的比較表來思考的圖。一張判斷表新業務應用程式要選WinForms還是WPF已經有既有資產還要不要走向WinUI用依觀點分列的比較表來思考

圖 5: 判斷表之後剩下的 2 個煩惱,用依觀點分列的比較表來思考。

4. 依觀點分列的比較表

這裡不是 官方的優劣表,而是相當貼近實務的比較。

觀點 WinForms WPF WinUI
快速做出小型輸入表單
以標準控制項為主的公司內部工具 △〜○
與資料繫結/MVVM 的契合度 ○〜◎
樣式/樣板/畫面表現力
與既有 Windows 桌面資產的親和度
現代的 Windows 風格
既有畫面的延續使用與階段性改版
只想追加 Windows App SDK 的功能
散發/更新/維運設計的輕重 △〜○
打造「全新、會長期成長的 Windows 專用產品 UI」

看這張表的訣竅,不是問 哪一個最強,而是問 哪一個摩擦最少

舉例來說,

  • 公司內部的設定工具
  • 設備設定畫面
  • 清單、明細、搜尋、設定、按鈕
  • 比起外觀,維運穩定與改版速度更重要

這種情況,WinForms 依然完全合理。

反過來,

  • 畫面數量多
  • 顯示狀態的切換很多
  • 想把 View 和邏輯分開
  • 想把資料的變化自然地接到 UI 上
  • 想用樣式/樣板統一管理 UI

這種情況,WPF 就很管用。67

而,

  • 想以 Windows 11 風格的外觀為前提
  • 想好好活用 Fluent
  • 想以高 DPI、觸控、現代的視窗 API 為前提
  • 是新專案,而且身為 Windows 專用產品,UI 給人的印象也很重要

這種情況,WinUI 就很自然。12

用摩擦最少來選顯示訣竅不是看哪一個最強而是看哪一個摩擦最少,以標準控制項為主的公司內部工具用WinForms,畫面數量多且想用MVVM的案子用WPF,以Fluent與最新Windows體驗為前提的案子用WinUI最自然的圖。哪一個摩擦最少公司內部工具、以標準控制項為主畫面數量多且想用MVVM以Fluent、最新Windows體驗為前提WinFormsWPFWinUI

圖 6: 不是看「哪一個最強」,而是用「哪一個摩擦最少」來分別使用這 3 個。

4.1 用最小的程式碼看「表現力的差異」

上表的「與資料繫結/MVVM 的契合度」,光用文字說明不容易抓到重點。這裡用最小的程式碼並排,看看 同一個畫面用 WinForms 和 WPF 寫出來會有什麼差別

要做的只是「一個文字方塊加一個儲存按鈕」的畫面。

WinForms:由 Designer 產生 *.Designer.cs,然後在事件處理常式裡從畫面取出值。

// MainForm.Designer.cs — Designer 產生的那一側。不是手寫的地方
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.Button saveButton;

private void InitializeComponent()
{
    this.nameTextBox = new System.Windows.Forms.TextBox();
    this.saveButton = new System.Windows.Forms.Button();
    this.SuspendLayout();

    this.nameTextBox.Location = new System.Drawing.Point(12, 12);
    this.nameTextBox.Size = new System.Drawing.Size(200, 23);

    this.saveButton.Location = new System.Drawing.Point(218, 12);
    this.saveButton.Size = new System.Drawing.Size(75, 23);
    this.saveButton.Text = "儲存";
    this.saveButton.Click += new System.EventHandler(this.SaveButton_Click);

    this.Controls.Add(this.nameTextBox);
    this.Controls.Add(this.saveButton);
    this.ResumeLayout(false);
}
// MainForm.cs — 這一側才是手寫的
public partial class MainForm : Form
{
    private readonly EditorService _service;

    public MainForm(EditorService service)
    {
        _service = service;
        InitializeComponent();
    }

    private void SaveButton_Click(object sender, EventArgs e)
    {
        // 直接從畫面的控制項取出值再傳過去
        _service.Save(this.nameTextBox.Text);
    }
}

WPF:XAML 只寫「跟什麼連在一起」,值的進出交給 Binding 處理。

<!-- MainWindow.xaml -->
<Window x:Class="MyApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="編輯" Width="360" Height="120">
    <StackPanel Orientation="Horizontal" Margin="12">
        <TextBox Width="200"
                 Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
        <Button Width="75" Margin="6,0,0,0" Content="儲存"
                Command="{Binding SaveCommand}" />
    </StackPanel>
</Window>
// MainWindow.xaml.cs — 忘了傳 DataContext 的話,Binding 什麼都不會發生
public partial class MainWindow : Window
{
    public MainWindow(EditorService service)
    {
        InitializeComponent();
        this.DataContext = new MainViewModel(service);
    }
}
// MainViewModel.cs — 不認識畫面的那一側。單元測試也寫在這裡
public sealed class MainViewModel : INotifyPropertyChanged
{
    private readonly EditorService _service;
    private string _name = string.Empty;

    public MainViewModel(EditorService service)
    {
        _service = service;
        SaveCommand = new RelayCommand(() => _service.Save(Name));
    }

    public string Name
    {
        get => _name;
        set
        {
            if (_name == value) return;
            _name = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
        }
    }

    public ICommand SaveCommand { get; }

    public event PropertyChangedEventHandler PropertyChanged;
}

RelayCommand 是實作 ICommand 的小類別,CommunityToolkit.Mvvm 這類函式庫裡也有,自己寫大約 20 行也做得出來。

只看行數的話,WPF 比較多。差距是從這裡才開始出現的。

  WinForms WPF
從畫面取值的位置 在事件處理常式裡直接讀 nameTextBox.Text Name 屬性。不碰 View
為儲存處理寫單元測試 必須把 Form 立起來 直接 new 出 MainViewModel 就能呼叫
把同一個輸入欄位放到另一個畫面 重新擺一次控制項,處理常式也要重寫 對同一個 ViewModel 套上另一個 View
讓全部畫面的外觀一致 逐一調整各控制項的屬性 把 Style / Template 放在一個地方

畫面只有 3 個時 WinForms 比較快,到了 30 個時 WPF 比較輕鬆,這就是這個差距在實務上的意義。

值的流動方式的差異顯示WinForms由事件處理常式直接從畫面的控制項取出值再交給服務,而WPF由Binding連接View與ViewModel,再由不認識畫面的ViewModel呼叫服務,兩者在值的流動方式上的差異的圖。WPFWinFormsBindingView的XAMLViewModel呼叫服務事件處理常式View的控制項直接呼叫服務3個畫面時很快30個畫面也很輕鬆

圖 7: WinForms 直接從畫面取值,WPF 則透過 Binding 交由 ViewModel 承接。

5. 各自適合什麼樣的案子

5.1 WinForms

WinForms 常常被莫名其妙地看輕,但 要快速做出以標準控制項為主的業務畫面,就這一點來說,它現在依然不可小看。35

特別適合的,例如是這類案子。

  • 公司內部用的設定工具
  • 設備、量測儀器、監控工具的設定畫面
  • 管理畫面、搜尋畫面、清單 + 明細
  • 既有 WinForms 資產很大的案子
  • 開發風格強烈以 Windows Forms Designer 為中心的團隊

WinForms 的強項在於,不必帶進困難的思想,也能相當快地做出接近成品的畫面。 表單、按鈕、標籤、文字方塊、資料格線。 如果主戰場就是這個世界,它相當能打。

不過,弱點也很明確。

  • 想把整個畫面的外觀大幅統一
  • 想用樣式與樣板控制 UI
  • 想以資料繫結為主來處理複雜的狀態變化
  • 想把畫面邏輯乾淨地分離出來

這幾點,WPF 或 WinUI 會直接了當得多。

用 WinForms 做大型應用程式,稍不注意就容易變成 事件處理常式的叢林。 所以如果要選 WinForms,至少

  • 讓畫面的職責保持小
  • 以 UserControl 為單位切分
  • 意識到 Presenter / ViewModel 等級的邊界
  • 不要把業務邏輯黏死在畫面事件裡

這幾點最好一開始就先定下來,後面會比較安穩。

避免事件處理常式的叢林顯示用WinForms做大型應用程式容易變成事件處理常式的叢林,因此要一開始就決定讓畫面職責保持小、以UserControl為單位切分、意識到Presenter或ViewModel等級的邊界的圖。大型WinForms應用程式容易變成事件處理常式的叢林讓畫面職責保持小以UserControl為單位切分意識到邊界不要把業務邏輯寫進畫面事件

圖 8: 大型 WinForms 應用程式,只要一開始就定好職責切分的做法就會安穩許多。

另外,實務上相當重要的一點是,不會因為想用 Windows App SDK 就必須捨棄 WinForms。 官方也有把 Windows App SDK 的功能加到既有 WinForms 應用程式的路徑。910

也就是說,WinForms 可以

  • UI 維持原樣
  • 只把需要的 Windows 功能現代化

用這樣的方式來選。 這是很現實的折衷點。

維持WinForms也能現代化的路顯示不會因為想使用Windows App SDK就必須捨棄WinForms,可以維持UI原樣而只把需要的Windows功能現代化,是很現實的折衷點的圖。想使用Windows App SDK不必捨棄WinFormsUI維持原樣只把需要的功能現代化現實的折衷點

圖 9: WinForms 可以保住 UI,只把需要的 Windows 功能現代化。

5.2 WPF

以 Windows 桌面的 .NET UI 來看,WPF 是 平衡最好的核心4

強項很明確。

  • 可以用 XAML 宣告式地描述畫面
  • Data Binding 很強
  • 可以使用 Style / Template
  • 可以使用 Command
  • 容易把 View 和邏輯分開
  • 中~大規模的畫面容易整理

WPF 的官方文件也把資料繫結說明成 WPF 的核心功能,命令則被整理成把輸入與執行邏輯分開的機制。67

所以,它適合像這樣的案子。

  • 畫面數量多的業務應用程式
  • 清單、明細、編輯、搜尋、狀態顯示很多
  • 多人長期維護的 Windows 應用程式
  • 想把 View 和邏輯分開
  • 希望在將來改版時,外觀與行為的職責已經先分開
  • 用 WinForms 的話畫面很快就會變得笨重

新開發 Windows 專用業務應用程式而猶豫不決時, WPF 現在依然是安全的第一候選。 在這裡用「WPF 太舊所以不考慮」把它切掉,有點粗暴。

新業務應用程式安全的第一候選顯示畫面數量多、想把View與邏輯分開、由多人長期維護的中~大規模Windows業務應用程式,WPF現在依然是安全的第一候選的圖。畫面數量多的業務應用程式WPF是安全的第一候選想把View與邏輯分開多人長期維護用「太舊所以不考慮」切掉太粗暴

圖 10: 畫面數量多又要長期維護的新業務應用程式,WPF 是安全的第一候選。

反而是,

  • 已經有既有 WPF 資產
  • 已經有既有 XAML / MVVM 的實務心得
  • 沒有到 Fluent 最優先的程度
  • 但想把 UI 設計得比 WinForms 更乾淨

這種情況下,WPF 方向最對,是很常見的事。

當然,WPF 也有它的脾氣。

  • XAML 寫得太講究就會變得難讀
  • 自訂控制項與樣板疊太多層,維護就會很重
  • 太偏向「什麼都用 Binding 解決」的方針,反而會讓處理流程難以追蹤

這些確實存在,但與其說是 WPF 不好,不如說是 表現力強的工具隨手亂揮,反作用力也大

WPF 也可以加上 Windows App SDK 的一部分功能。 也就是說,存在 維持 WPF 就把 Windows 功能現代化 這條路。810

因此,比起

  • 把 WPF 全部丟掉,全面遷移到 WinUI

不如

  • 把 WPF 靠向現行的 .NET
  • 只把需要的 Windows 功能用 Windows App SDK 補上
  • 從新的大型功能開始整理結構

在實務上,後者能贏的場合更多。

比起WPF全面遷移不如漸進顯示比起把WPF全部丟掉全面遷移到WinUI,把WPF靠向現行.NET、只用Windows App SDK補上需要的Windows功能、從新的大型功能開始整理結構,在實務上更容易獲勝的圖。把WPF靠向現行.NET只用SDK補上需要的功能從新的大型功能開始整理比全面遷移更容易獲勝

圖 11: WPF 與其全面遷移,不如靠向現行 .NET 再補功能的漸進做法更容易獲勝。

5.3 WinUI

要做 全新的 Windows 專用應用程式 時,WinUI 是現代化的正解。12

官方的定位是,

  • 針對最新的硬體與輸入最佳化
  • 高 DPI
  • 流暢的動畫
  • Windows App SDK 的一部分

以上這幾點。1

所以,它適合這類案子。

  • Windows 專用的新產品
  • UI 給人的印象或體驗本身很重要
  • 想直接了當地使用 Fluent
  • 想貼近 Windows 11 的現況
  • 想以新的視窗 API 或最新的 Windows 體驗為前提

選 WinUI 有紮實理由的案子, 大致上都是 「想把現在的 Windows 體驗放進產品」而不是「外觀比較新」 的案子。

分辨選WinUI的理由顯示選WinUI有紮實理由的案子,不是因為外觀比較新,而是想把現在的Windows體驗放進產品的案子的圖。有理由選WinUI的案子不是「外觀比較新」而是「把現在的Windows體驗放進產品」Windows專用的新產品、UI印象很重要

圖 12: WinUI 的採用理由不在「新」,而在「把現在的 Windows 體驗放進來」。

另一方面,也有需要注意的地方。

5.3.1 WinUI 不是「只是比較新的 WPF」

因為都用 XAML,看起來很接近,但

  • 底層的 API
  • 控制項周邊
  • 專案結構
  • 部署/packaging 的思考方式
  • 與 Windows App SDK 的相處方式

都不一樣。

也就是說,把它當成 可以從 WPF 輕鬆替換過去的目標,有點危險。

WinUI不是只是比較新的WPF顯示因為都用XAML所以看起來很接近,但底層API、控制項周邊、專案結構、部署與packaging的思考方式、與Windows App SDK的相處方式都不同,把它當成可以從WPF輕鬆替換的目標很危險的圖。都用XAML所以看起來很接近但不同的地方很多底層API與控制項結構與packaging與SDK的相處方式當成輕鬆替換的目標很危險

圖 13: 就算 XAML 一樣,WinUI 也不是可以從 WPF 輕鬆替換過去的目標。

5.3.2 選了 WinUI,散發的問題就會浮到前面

WinUI 3 應用程式 預設是 packaged。 另一方面,Windows App SDK 本身 packaged / unpackaged 兩種都支援13142

這裡重要的是,

  • 要怎麼散發
  • 執行階段要怎麼安裝
  • 需不需要 package identity
  • 是公司內部散發、Store、MSIX,還是既有的 EXE / MSI 路線

這幾件事 最好提早決定

只是,光說「提早確認」也很難知道要看什麼,所以把確認的內容寫在這裡。

首先,要決定的軸線有 2 個。1315

  • packaging:這個應用程式有沒有 package identity
  • runtime:Windows App SDK 要用 framework-dependent,還是 self-contained 一起帶著走
先決定的2個軸線顯示WinUI的散發要先決定應用程式是否具有package identity的packaging軸線,以及Windows App SDK要用framework-dependent還是self-contained一起帶著走的runtime軸線這2個的圖。散發的設計packaging的軸線runtime的軸線是否具有package identityframework-dependent還是一起帶著走

圖 14: 散發要先決定 packaging 與 runtime 這 2 個軸線。

packaging 這一側的選項有 3 個。13

模型 package identity 安裝程式 適合的場合
packaged(MSIX) MSIX 取代安裝程式 新專案開發、上架 Store、用 Intune 等做企業散發
指向外部位置的 packaged(sparse package) 直接沿用既有的安裝程式 已有自家安裝程式的既有 Win32 / WPF / WinForms
unpackaged MSI / EXE / xcopy 公司內部工具、廣泛散發的傳統 Win32

接著,從功能面判斷需不需要 package identity。 官方明確寫出「沒有 package identity 就無法運作」的功能,例如是這些。13

  • 背景工作
  • 推播通知(WNS)
  • 共用目標
  • 檔案總管的操作功能表擴充
  • 檔案類型與 URI 配置的關聯
  • 啟動工作
  • App Service
  • Windows AI API

確認的步驟,照這個順序在實務上最順。

  1. 從需求反推。 有沒有打算使用上面清單裡的功能。只要有一項,就需要 packaged 這一側。
  2. 看看能不能捨棄既有的安裝程式。 不想捨棄的話,答案就不是全面遷移到 MSIX,而是 指向外部位置的 packaged。既有的二進位檔擺放方式與更新機制都可以維持原樣,只補上 identity。13
  3. 在執行階段確認。 執行中的處理程序有沒有 identity,可以用 GetCurrentPackageFullName 判定。沒有 identity 時會傳回 APPMODEL_ERROR_NO_PACKAGE。反過來說,呼叫 Windows API 時出現 E_ILLEGAL_METHOD_CALLAPPMODEL_ERROR_NO_PACKAGE就是踩到 package identity 需求的訊號13
  4. 在電腦端確認。 已安裝的套件可以用 PowerShell 的 Get-AppxPackage 列出來。
  5. 最後決定 runtime。 想用 xcopy 或 zip 散發就選 self-contained,要上架 Store 的話,framework-dependent 是預設路線。15

WinForms / WPF 的散發同樣重要,但 WinUI 這一塊更容易浮到前景。新的 WinUI 3 應用程式 預設就是 packaged,什麼都沒決定的話,就會自動走上 MSIX 路線。13 本來以為只是在決定 UI,實際上決定的是散發策略——這是這個世界稍微麻煩的地方。

package identity的確認步驟顯示從需求反推需要package identity的功能,看看能不能捨棄既有安裝程式,在執行階段與電腦端確認,最後決定runtime這5個步驟的確認流程的圖。1. 從需求反推2. 看能不能捨棄安裝程式3. 在執行階段確認4. 在電腦端確認5. 決定runtime不想捨棄就用指向外部位置的packaged用GetCurrentPackageFullName判定

圖 15: package identity 要不要,照需求、安裝程式、執行階段、電腦的順序確認。

5.3.3 「在既有 WPF / WinForms 裡一點一點混入 WinUI」要先做實驗

這裡是最容易讓期待膨脹的地方。 不過,Microsoft 的 FAQ 也寫著 除非已經準備好完全遷移 UI 框架,否則多半用不了 WinUI 這個意思。 再者,XAML Islands 這一塊,官方文件雖然給出了嵌入既有桌面應用程式的路徑,但 Windows App SDK 1.4 的版本資訊裡也寫著 目前主要測試過的是在 C++ 應用程式上的使用,並未納入給 WPF / WinForms 用的便利包裝元素1011

也就是說,

  • 「看起來可以階段性遷移」
  • 「看起來一點一點填進去就好」

這種想法,就算構想上很吸引人,在當成案子的主策略之前,最好先小規模驗證

WinUI 在

  • 從新專案開始做
  • 以 Windows 專用產品的身分打造體驗

的時候方向最對。 反過來,要當作既有 WPF / WinForms 全面替換的承接對象,就需要理由與驗證。

階段性遷移在當成主策略前先驗證顯示一點一點混入WinUI的階段性遷移在構想上雖然吸引人,但FAQ指出除非準備好完全遷移否則多半用不了,XAML Islands也沒有給WPF或WinForms用的便利包裝,因此在當成主策略前應該先小規模驗證的圖。想一點一點混入WinUI構想上很吸引人FAQ的意思是以完全遷移為前提沒有給WPF / WinForms用的包裝當成主策略前先小規模驗證

圖 16: 「一點一點混入 WinUI」在當成主策略之前,要先小規模驗證。

6. 常見的判斷失誤

6.1 「因為最新所以選 WinUI」

這個理由很好懂,但相當危險。

選新技術的理由,最好用 是不是有非它不可才能得到的價值 來看。

  • 現代的 Windows 體驗是不是產品價值
  • 想不想直接了當地使用 Fluent
  • 是不是新產品
  • 能不能接受散發/維運的前提

這幾點如果是 yes,WinUI 就很有力。 反過來,如果只是「感覺有未來性」,成本的說明力道就很弱。

不是「因為最新」而是用價值來選顯示選新技術的理由應該看是不是有非它不可才能得到的價值,現代體驗是不是產品價值等問題若為yes則WinUI很有力,只有「感覺有未來性」則成本說明力道很弱的圖。yes只有「感覺有未來性」選新技術的理由是否有非它不可才能得到的價值WinUI很有力成本的說明力道很弱

圖 17: 不是「因為最新」,而是看有沒有非它不可才能得到的價值。

6.2 「想用 Windows App SDK 就非得改成 WinUI」

這一點很容易被誤解,但並非如此。

Windows App SDK 也可以加到既有的 WPF / WinForms 上。 官方 FAQ 也整理過,WPF / MFC / WinForms 應用程式可以使用與 WinUI 無關的 Windows App SDK API。1089

例如,

  • App Lifecycle
  • Windowing
  • Toast Notifications

這類功能,有機會 在維持現在的 UI 之下納入10

6.3 「WPF / WinForms 已經完蛋了」

這裡同樣,最好不要草率地判出局。

WinForms 和 WPF 在現行的 .NET 上都持續有文件與遷移路徑,官方也把它們當成現役的 Windows 桌面 UI 看待。34

作為長期維護的判斷材料,比起「文件還在不在」,新功能有沒有持續進來 是更好懂的指標。從這個觀點看,3 個的狀況如下。

  最近的動向 看法
WPF .NET 9 加入了給 Windows 11 用的 Fluent 佈景主題,可以用 ThemeMode 屬性切換 light / dark / system,也支援 Windows 的輔色16 「因為外觀老舊所以選 WinUI」這個理由,比以前更站不住腳了
WinForms .NET 9 加入了深色模式的暫定支援,可以用 Application.SetColorMode 切換。不過 這是實驗性功能,文件寫著正式支援以 .NET 10 為目標。非同步相關的 API 也增加了17 新功能是有進來,但其中混著帶實驗性旗標的東西
WinUI / Windows App SDK 以與 .NET 不同的獨立發行週期持續更新18 更新很活躍,但 必須和 .NET 的版本分開追蹤,維護計畫就多出一個項目

也就是說,從長期維護的觀點可以這樣讀。

  • WPF 和 WinForms 不是「凍結後放著不管」,而是 搭著每年的 .NET 發行持續加入功能。不過 WinForms 的重點功能有些還在實驗階段,採用時機需要確認。
  • 選了 WinUI,就等於要 分別管理 .NET 的支援期限與 Windows App SDK 的支援期限。長期案子裡,這一點會在不知不覺間發揮影響。
  • 不管選哪一個,都沒有「10 年後不改也能跑」的保證,所以 一開始就先決定要追隨到哪個版本 在實務上比較好。
長期維護的讀法顯示WPF與WinForms搭著每年的.NET發行加入功能,選了WinUI就要分別管理.NET與Windows App SDK的支援期限,因此要一開始就決定追隨到哪個版本的圖。WPF / WinForms搭著.NET發行加入功能WinUI分別管理SDK的期限一開始就決定追隨到哪裡

圖 18: 長期維護要看更新是搭著什麼來的,並先決定追隨方針。

特別是業務應用程式,

  • 既有資產
  • 第三方控制項
  • 畫面數量
  • 報表與列印
  • 設備介接
  • 散發流程

這些常常比 UI 框架新不新更有份量。

6.4 「乾脆全面重寫」

全面重寫不是技術選型,而更接近 事業判斷

如果已經有既有應用程式,最先該看的是這幾點。

  1. 真正困擾的是什麼
  2. 是 UI 的問題,還是架構的問題
  3. 相依 DLL / COM / OCX / 報表 / 散發,是不是才是真正的重擔
  4. 不把 UI 全部換掉,困擾的事情能不能解決

UI 重寫很華麗,成本也很華麗。 而且,就算外觀變新了,周邊的麻煩大致上還是會留著。

全面重寫前要看的4個問題顯示全面重寫不是技術選型而更接近事業判斷,要先看真正困擾的是什麼、是UI還是架構的問題、相依與散發是不是真正的重擔、不換UI能不能解決的圖。1. 真正困擾的是什麼2. 是UI還是架構的問題3. 相依與散發是不是重擔4. 不換UI能不能解決重寫的成本也很華麗

圖 19: 決定全面重寫之前,先用 4 個問題確認困擾的真面目。

6.5 「之後用 XAML Islands 總會有辦法」

這個期待可以理解。 但 不要一開始就把它當成救生艇 比較安全。1011

階段性遷移,最好先把

  • 想嵌入的控制項是什麼
  • 焦點、輸入、DPI、佈景主題會變成怎樣
  • 那個宿主結構實際上會不會穩定

這幾點先小規模試過。

XAML Islands要先小規模試顯示階段性遷移要先小規模試過想嵌入的控制項是什麼、焦點與輸入與DPI與佈景主題會變成怎樣、宿主結構會不會穩定,不要一開始就把它當成救生艇的圖。「之後總會有辦法」的期待想嵌入的控制項是什麼焦點・輸入・DPI・佈景主題宿主結構會不會穩定先小規模試

圖 20: XAML Islands 不要當成救生艇,先把 3 個點小規模試過。

7. 以既有應用程式為前提時的看法

這裡比新專案更重要,因為既有的部分才是關鍵。

7.1 已經有既有 WinForms 的話

先別急著跳到 WinUI,而是確認這幾點。

  • 能不能靠向現行的 .NET
  • 需不需要改成 64bit
  • 能不能把 async / await、例外處理、設定、日誌整理一遍
  • 能不能靠切分畫面或改成 UserControl 提高可維護性
  • 能不能只用 Windows App SDK 補上需要的 Windows 功能

看起來是 WinForms 的問題,實際上只是

  • 畫面和邏輯混在一起
  • 執行緒邊界很草率
  • 設定 / 檔案 / COM / DB 的職責全塞在一起

的情況並不少見。

這種時候,就算搬到 WinUI,問題也只是換個名字留下來而已。

問題只是換個名字留下來顯示看起來是WinForms的問題,實際上常常是畫面與邏輯混在一起、執行緒邊界草率、職責全塞在一起造成的,這種情況就算搬到WinUI問題也只是換個名字留下來的圖。看起來是WinForms的問題其實是結構的問題畫面與邏輯混在一起草率的執行緒邊界職責全塞在一起搬到WinUI也只是換個名字留下來

圖 21: 看起來像 UI 問題的結構問題,換掉框架也還是會留著。

7.2 已經有既有 WPF 的話

WPF 很容易活用既有資產。

  • XAML 資產
  • Binding
  • Style / Template
  • Command
  • MVVM

要捨棄這些的理由,應該相當明確才行。

舉例來說,

  • 想全面翻新產品 UI
  • 想以 Fluent 為主軸
  • 要把新模組切出去當成另一個產品
  • 想以 Windows 專用產品的身分靠向新的體驗

這些就構成考慮 WinUI 的理由。 但如果只是「因為 WPF 太舊」,力道就很弱。

7.3 真正沉重的往往是 UI 以外的部分

實務上,累人的意外是這一帶。

  • ActiveX / OCX
  • COM interop
  • 自訂報表
  • 列印
  • Excel / Office 介接
  • 原生 DLL
  • 32 位元與 64 位元的錯位
  • 安裝程式、權限、更新、簽署

輕忽這裡的話,就算只把 UI 弄漂亮,整個案子也不會變輕。

所以,既有應用程式的遷移, 不要只看 UI 框架,而是先連相依邊界一起盤點 才對。

連相依邊界一起盤點顯示實務上沉重的多半是ActiveX與COM、報表與列印、原生DLL、安裝程式與更新等UI以外的部分,因此不要只看UI框架,先連相依邊界一起盤點的圖。ActiveX / COM interop真正沉重的是UI以外報表・列印・Office介接安裝程式・權限・更新・簽署先盤點相依邊界只把UI弄漂亮不會變輕

圖 22: 遷移時真正沉重的是 UI 以外的相依,要先做盤點。

8. 猶豫時最後檢視的 5 個問題

最後真的拿不定主意,就把這 5 個問題依序套上去。

8.1 既有資產大不大

  • 大 → 基本上維持既有系譜
  • 小/沒有 → 進入新專案選型

8.2 那個應用程式一定要「Windows 風格的現代體驗」嗎

  • 一定要 → WinUI 很有力
  • 沒到那個程度 → 確認 WPF / WinForms 是否已經足夠

8.3 畫面是以標準表單為主,還是需要 XAML 式的表現力

  • 以標準表單為主 → WinForms
  • 樣式/樣板/Binding/MVVM 很重要 → WPF

8.4 想要的是 UI 全面翻新,還是追加 Windows 功能

  • UI 全面翻新 → 考慮 WinUI
  • 只是追加功能 → 先考慮現行的 WPF / WinForms + Windows App SDK

8.5 散發/更新/維運要怎麼做,能不能先說明清楚

  • 還很模糊 → 選 WinUI 就要提早把 packaging / deployment 敲定
  • 想緊貼既有維運 → 多半是 WPF / WinForms 摩擦比較少
最後檢視的5個問題的流程顯示依序套上既有資產大不大、現代體驗是不是必要、以標準表單為主還是需要表現力、散發與更新與維運能不能說明清楚這些問題來收斂選項的流程的圖。小・沒有必要沒到那個程度表現力很重要既有資產大不大基本上維持既有系譜現代體驗是不是必要WinUI很有力是否以標準表單為主WinFormsWPF只是追加功能就先考慮SDK提早敲定packaging與散發

圖 23: 猶豫時,依既有資產、體驗、畫面性質的順序套上問題來收斂。

用這 5 個問題就能收斂不少。 最後粗略地整理一下,大概是這樣。

  • 快速做出來的公司內部表單 → WinForms
  • 長期成長的 Windows 業務應用程式 → WPF
  • 全新的現代 Windows 產品 UI → WinUI
  • 活用既有資產,只把 Windows 功能現代化 → 現行框架 + Windows App SDK

9. 總結

WinForms、WPF、WinUI 的選型, 不是把它們照新舊排好然後挑最右邊的遊戲

最先該看的是這 4 點。

  1. 既有資產在哪裡
  2. 畫面是以表單為主,還是以表現力為主
  3. Windows 風格的現代 UI 是不是產品需求
  4. 散發/更新/維運要怎麼跑

這 4 點一旦看清楚,方針大致就定了。

總結的4個問題顯示既有資產在哪裡、畫面是以表單為主還是以表現力為主、現代UI是不是產品需求、散發與更新與維運要怎麼跑這4點看清楚後方針大致就定了的圖。既有資產方針大致就定了畫面的性質現代UI的需求散發與維運

圖 24: 4 個問題看清楚後,框架的方針大致就定了。

  • 手上有大量既有 WinForms,就先繼續用 WinForms
  • 手上有大量既有 WPF,就先繼續用 WPF
  • 新專案以標準表單為主就選 WinForms
  • 新專案是中~大規模的 Windows 業務應用程式就選 WPF
  • 新專案的需求本身就是現代 Windows 體驗就選 WinUI
  • 只是想用 Windows App SDK,就不要一口氣全部換成 WinUI

最想避免的是,

  • 因為舊所以丟掉
  • 因為新所以選它
  • 抱著「途中總會有辦法」的心態開始

這 3 件事。

Windows 桌面是一個 資產、散發、維運、相依性 比外觀更有份量的世界。 所以,比起新鮮感,更重視與既有資產、散發、維運摩擦最少的選擇,在實務上才站得住腳。

10. 參考資料

  1. Microsoft Learn, “WinUI 3 - Windows apps” / Microsoft Learn, “Modernize your desktop apps for Windows”  2 3 4 5 6 7

  2. Microsoft Learn, “Windows App SDK”  2 3 4 5 6 7 8

  3. Microsoft Learn, “什麼是 Windows Forms - Windows Forms”  2 3 4 5

  4. Microsoft Learn, “什麼是 Windows Presentation Foundation - WPF”  2 3 4 5

  5. Microsoft Learn, “What is Windows Forms Designer?”  2

  6. Microsoft Learn, “Data binding overview - WPF”  2 3

  7. Microsoft Learn, “Commanding Overview - WPF”  2 3

  8. Microsoft Learn, “在 WPF 應用程式中使用 Windows 應用程式 SDK”  2 3

  9. Microsoft Learn, “Use the Windows App SDK in a Windows Forms (WinForms) app”  2 3

  10. Microsoft Learn, “Windows 開發者常見問題集”  2 3 4 5 6 7 8 9

  11. Microsoft Learn, “Windows App SDK 1.4 release notes” / Microsoft Learn, “Windows App SDK”  2 3

  12. Microsoft Learn, “Windows data binding and MVVM” 

  13. Microsoft Learn, “Packaging overview - Windows apps” / Microsoft Learn, “Grant package identity by packaging with external location”  2 3 4 5 6 7

  14. Microsoft Learn, “Quick start: Set up your environment and create a WinUI 3 project” 

  15. Microsoft Learn, “Package and deploy Windows apps overview”  2

  16. Microsoft Learn, “What’s new in WPF for .NET 9” 

  17. Microsoft Learn, “What’s new in WinForms for .NET 9” 

  18. Microsoft Learn, “Windows App SDK release channels” 

共用相同標籤的最新文章。能以相近的主題延伸理解。

與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。

本文連結到以下服務頁面,歡迎從最接近的入口查看。

常見問題

整理諮詢這個主題時常見的問題。

WinUI 3 和 WPF 有什麼不同?
兩者都使用 XAML,但 WinUI 並不是「只是比較新的 WPF」。底層 API、控制項周邊、專案結構、部署與 packaging 的思考方式、以及和 Windows App SDK 的相處方式都不一樣。WPF 具備解析度無關的向量繪製、資料繫結、樣式與樣板、命令,是給中~大規模業務應用程式用的 UI 框架;WinUI 則是 Windows App SDK 的一部分,以 Fluent、高 DPI 與最新的 Windows 體驗為前提的現代 UI 框架。把它當成可以從 WPF 輕鬆替換過去的目標,是危險的。
新專案開發該選 WinForms、WPF 還是 WinUI?
看畫面的性質和產品需求而定。想快速做出以標準控制項與輸入表單為主的小~中規模公司內部工具,WinForms 現在依然相當強。畫面數量多,而且想好好運用資料繫結、樣式、樣板與 MVVM 的中~大規模業務應用程式,多半是 WPF 最不容易出問題。Windows 專用的新產品,如果 Fluent 與現代的 Windows 體驗直接構成產品價值,WinUI 就很有力。既有資產很大的時候,先以延續同一個系譜為基本前提來看。
WPF 和 WinForms 已經過時了嗎?
最好不要草率地把它們判出局。WinForms 和 WPF 在現行的 .NET 上都持續有文件與遷移路徑,官方也把它們當成現役的 Windows 桌面 UI 看待。特別是業務應用程式,既有資產、第三方控制項、報表與列印、設備介接、散發流程,這些常常比 UI 框架新不新更有份量。就算是新專案,WinForms 或 WPF 成為摩擦最少的選擇,也不是什麼稀奇的事。
要使用最新的 Windows 功能,就一定得遷移到 WinUI 嗎?
不必。Windows App SDK 和 WinUI 並不相同,WinUI 是 Windows App SDK 裡的 UI 框架部分。Windows App SDK 本身也可以加進 WPF / WinForms / Win32 的既有應用程式,App Lifecycle、Windowing、Toast Notifications 這類功能,有機會在維持現有 UI 的情況下納入。也就是說,存在一條「維持既有的 WPF / WinForms,只把需要的 Windows 功能現代化」的路,UI 全面遷移並不是必要條件。

作者檔案

本文作者的個人檔案頁面。

Go Komura

小村軟體有限公司 代表

以 Windows 軟體開發、技術諮詢與故障調查為中心,在難以重現的故障調查與既有資產仍在運作的專案上具有優勢。

回到部落格一覽