更新紀錄(2 筆,最後更新 2026年09月04日)
本文的修改紀錄。已保存的更新前版本,可透過附有 DOI 的永久連結閱讀。
引用本文(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
這類模糊的選法。
flowchart TB
accTitle: 模糊選法的風險
accDescr: 顯示「因為最新所以選WinUI、因為最熟悉所以選WinForms、因為感覺介於中間所以選WPF」這種模糊的選法很危險,實務上要用更明確的軸線來看的圖。
w1["因為最新所以選WinUI"] --> w4["模糊的選法"]
w2["因為最熟悉所以選WinForms"] --> w4
w3["因為感覺介於中間所以選WPF"] --> w4
w4 --> w5["實務上要用明確的軸線來看"]
圖 1: 不是靠「最新、最熟悉、感覺介於中間」,而是用明確的軸線來選。
在實務上,該看的軸線要更清楚一些。
- 是新專案開發,還是既有資產的延伸
- 畫面是以輸入表單為主,還是需要表現力
- Windows 風格的現代 UI 本身是不是產品價值
- 散發、更新、企業內維運要怎麼處理
- 開發風格是以 Windows Forms Designer 為中心,還是以 XAML/MVVM 為中心
本文把這些整理成一張判斷表。 另外,本文所說的 WinUI 主要是指 WinUI 3 + Windows App SDK。12
還有,這 3 個 全部都是 Windows 專用。 如果 macOS / Linux 也在視野內,那問題設定本身就不一樣了。341
flowchart TB
accTitle: 3個都是Windows專用
accDescr: 顯示WinForms、WPF、WinUI都是Windows專用,如果macOS或Linux也在視野內,問題設定本身就不同的圖。
t1["WinForms"] --> t4["全部都是 Windows 專用"]
t2["WPF"] --> t4
t3["WinUI"] --> t4
t4 -.-> t5["macOS / 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
簡單說,大致上就是這幾件事。
- 既有資產很大的話,先保住那個系譜
- 新專案要快速做出標準表單,就選 WinForms
- 新專案是會長期成長的 Windows 業務應用程式,就選 WPF
- 新專案的需求本身就是現代 Windows UI,就選 WinUI
- 只是想用 Windows App SDK,就不要一口氣全部換成 WinUI
框架選型既是 UI 技術的選型,同時也是 散發、維運、學習成本、遷移成本的選型。 這裡如果只用「新/舊」來決定,後續的散發設計與維護成本會回過頭來反噬。
flowchart TB
accTitle: 先講結論的決定方式
accDescr: 顯示既有資產很大就先保住那個系譜,新專案要快速做標準表單選WinForms,長期成長的Windows業務應用程式選WPF,需求本身就是現代Windows UI就選WinUI的決定方式的圖。
r1{"既有資產是否很大"} -->|"是"| r2["先保住那個系譜"]
r1 -->|"否,是新專案"| r3{"是否以標準表單為主"}
r3 -->|"是"| r4["WinForms"]
r3 -->|"否"| r5{"現代UI本身是不是需求"}
r5 -->|"否"| r6["WPF,長期成長的業務應用程式"]
r5 -->|"是"| r7["WinUI"]
r7 -.-> r8["只為了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」和「要不要加功能」就會被當成同一個題目,結論很難收斂。
flowchart TB
accTitle: Windows App SDK和WinUI不是同一件事
accDescr: 顯示WinUI是Windows App SDK的UI框架部分,而Windows App SDK本身也可以加到WPF、WinForms、Win32的既有應用程式上,因此「使用WinUI」的判斷與「使用SDK功能」的判斷是兩回事的圖。
sdk["Windows App SDK"] --> ui["WinUI,也就是其UI框架部分"]
sdk -.-> ex["也能加到 WPF / WinForms / Win32"]
ui --> d1["「使用WinUI」的判斷"]
ex --> d2["「使用SDK功能」的判斷"]
d1 --> d3["看似相近其實是不同的判斷"]
d2 --> d3
圖 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 個容易讓人猶豫的點。
- 新開發的 Windows 業務應用程式,要靠向 WinForms 還是 WPF
- 已經有既有 WPF / WinForms,還要不要走向 WinUI
這 2 點看著後面的比較表來想,會比較容易判斷。
flowchart TB
accTitle: 判斷表之後剩下的2個煩惱
accDescr: 顯示光靠一張判斷表,還會剩下新開發的Windows業務應用程式要選WinForms還是WPF,以及已經有既有WPF或WinForms還要不要走向WinUI這2點,要用後面的比較表來思考的圖。
hyo["一張判斷表"] --> n1["新業務應用程式要選WinForms還是WPF"]
hyo --> n2["已經有既有資產還要不要走向WinUI"]
n1 --> hik["用依觀點分列的比較表來思考"]
n2 --> hik
圖 5: 判斷表之後剩下的 2 個煩惱,用依觀點分列的比較表來思考。
4. 依觀點分列的比較表
這裡不是 官方的優劣表,而是相當貼近實務的比較。
| 觀點 | WinForms | WPF | WinUI |
|---|---|---|---|
| 快速做出小型輸入表單 | ◎ | ○ | ○ |
| 以標準控制項為主的公司內部工具 | ◎ | ○ | △〜○ |
| 與資料繫結/MVVM 的契合度 | △ | ◎ | ○〜◎ |
| 樣式/樣板/畫面表現力 | △ | ◎ | ◎ |
| 與既有 Windows 桌面資產的親和度 | ◎ | ○ | △ |
| 現代的 Windows 風格 | △ | ○ | ◎ |
| 既有畫面的延續使用與階段性改版 | ◎ | ◎ | △ |
| 只想追加 Windows App SDK 的功能 | ○ | ○ | ◎ |
| 散發/更新/維運設計的輕重 | ○ | ○ | △〜○ |
| 打造「全新、會長期成長的 Windows 專用產品 UI」 | △ | ○ | ◎ |
看這張表的訣竅,不是問 哪一個最強,而是問 哪一個摩擦最少。
舉例來說,
- 公司內部的設定工具
- 設備設定畫面
- 清單、明細、搜尋、設定、按鈕
- 比起外觀,維運穩定與改版速度更重要
這種情況,WinForms 依然完全合理。
反過來,
- 畫面數量多
- 顯示狀態的切換很多
- 想把 View 和邏輯分開
- 想把資料的變化自然地接到 UI 上
- 想用樣式/樣板統一管理 UI
而,
- 想以 Windows 11 風格的外觀為前提
- 想好好活用 Fluent
- 想以高 DPI、觸控、現代的視窗 API 為前提
- 是新專案,而且身為 Windows 專用產品,UI 給人的印象也很重要
flowchart TB
accTitle: 用摩擦最少來選
accDescr: 顯示訣竅不是看哪一個最強而是看哪一個摩擦最少,以標準控制項為主的公司內部工具用WinForms,畫面數量多且想用MVVM的案子用WPF,以Fluent與最新Windows體驗為前提的案子用WinUI最自然的圖。
k0["哪一個摩擦最少"] --> k1["公司內部工具、以標準控制項為主"]
k0 --> k2["畫面數量多且想用MVVM"]
k0 --> k3["以Fluent、最新Windows體驗為前提"]
k1 --> k4["WinForms"]
k2 --> k5["WPF"]
k3 --> k6["WinUI"]
圖 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 比較輕鬆,這就是這個差距在實務上的意義。
flowchart TB
accTitle: 值的流動方式的差異
accDescr: 顯示WinForms由事件處理常式直接從畫面的控制項取出值再交給服務,而WPF由Binding連接View與ViewModel,再由不認識畫面的ViewModel呼叫服務,兩者在值的流動方式上的差異的圖。
subgraph wf["WinForms"]
a1["View的控制項"] --> a2["事件處理常式"]
a2 --> a3["直接呼叫服務"]
end
subgraph wp["WPF"]
b1["View的XAML"] --> b2["Binding"]
b2 --> b3["ViewModel"]
b3 --> b4["呼叫服務"]
end
a3 -.-> c1["3個畫面時很快"]
b4 -.-> c2["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 等級的邊界
- 不要把業務邏輯黏死在畫面事件裡
這幾點最好一開始就先定下來,後面會比較安穩。
flowchart TB
accTitle: 避免事件處理常式的叢林
accDescr: 顯示用WinForms做大型應用程式容易變成事件處理常式的叢林,因此要一開始就決定讓畫面職責保持小、以UserControl為單位切分、意識到Presenter或ViewModel等級的邊界的圖。
mo["大型WinForms應用程式"] --> ha["容易變成事件處理常式的叢林"]
ha --> p1["讓畫面職責保持小"]
ha --> p2["以UserControl為單位切分"]
ha --> p3["意識到邊界"]
p3 -.-> p4["不要把業務邏輯寫進畫面事件"]
圖 8: 大型 WinForms 應用程式,只要一開始就定好職責切分的做法就會安穩許多。
另外,實務上相當重要的一點是,不會因為想用 Windows App SDK 就必須捨棄 WinForms。 官方也有把 Windows App SDK 的功能加到既有 WinForms 應用程式的路徑。910
也就是說,WinForms 可以
- UI 維持原樣
- 只把需要的 Windows 功能現代化
用這樣的方式來選。 這是很現實的折衷點。
flowchart TB
accTitle: 維持WinForms也能現代化的路
accDescr: 顯示不會因為想使用Windows App SDK就必須捨棄WinForms,可以維持UI原樣而只把需要的Windows功能現代化,是很現實的折衷點的圖。
g1["想使用Windows App SDK"] --> g2["不必捨棄WinForms"]
g2 --> g3["UI維持原樣"]
g2 --> g4["只把需要的功能現代化"]
g3 --> g5["現實的折衷點"]
g4 --> g5
圖 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 太舊所以不考慮」把它切掉,有點粗暴。
flowchart TB
accTitle: 新業務應用程式安全的第一候選
accDescr: 顯示畫面數量多、想把View與邏輯分開、由多人長期維護的中~大規模Windows業務應用程式,WPF現在依然是安全的第一候選的圖。
j1["畫面數量多的業務應用程式"] --> j4["WPF是安全的第一候選"]
j2["想把View與邏輯分開"] --> j4
j3["多人長期維護"] --> j4
j4 -.-> j5["用「太舊所以不考慮」切掉太粗暴"]
圖 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 補上
- 從新的大型功能開始整理結構
在實務上,後者能贏的場合更多。
flowchart TB
accTitle: 比起WPF全面遷移不如漸進
accDescr: 顯示比起把WPF全部丟掉全面遷移到WinUI,把WPF靠向現行.NET、只用Windows App SDK補上需要的Windows功能、從新的大型功能開始整理結構,在實務上更容易獲勝的圖。
z1["把WPF靠向現行.NET"] --> z2["只用SDK補上需要的功能"]
z2 --> z3["從新的大型功能開始整理"]
z3 -.-> z4["比全面遷移更容易獲勝"]
圖 11: WPF 與其全面遷移,不如靠向現行 .NET 再補功能的漸進做法更容易獲勝。
5.3 WinUI
要做 全新的 Windows 專用應用程式 時,WinUI 是現代化的正解。12
官方的定位是,
- 針對最新的硬體與輸入最佳化
- 高 DPI
- 流暢的動畫
- Windows App SDK 的一部分
以上這幾點。1
所以,它適合這類案子。
- Windows 專用的新產品
- UI 給人的印象或體驗本身很重要
- 想直接了當地使用 Fluent
- 想貼近 Windows 11 的現況
- 想以新的視窗 API 或最新的 Windows 體驗為前提
選 WinUI 有紮實理由的案子, 大致上都是 「想把現在的 Windows 體驗放進產品」而不是「外觀比較新」 的案子。
flowchart TB
accTitle: 分辨選WinUI的理由
accDescr: 顯示選WinUI有紮實理由的案子,不是因為外觀比較新,而是想把現在的Windows體驗放進產品的案子的圖。
y1["有理由選WinUI的案子"] --> y2["不是「外觀比較新」"]
y2 --> y3["而是「把現在的Windows體驗放進產品」"]
y3 -.-> y4["Windows專用的新產品、UI印象很重要"]
圖 12: WinUI 的採用理由不在「新」,而在「把現在的 Windows 體驗放進來」。
另一方面,也有需要注意的地方。
5.3.1 WinUI 不是「只是比較新的 WPF」
因為都用 XAML,看起來很接近,但
- 底層的 API
- 控制項周邊
- 專案結構
- 部署/packaging 的思考方式
- 與 Windows App SDK 的相處方式
都不一樣。
也就是說,把它當成 可以從 WPF 輕鬆替換過去的目標,有點危險。
flowchart TB
accTitle: WinUI不是只是比較新的WPF
accDescr: 顯示因為都用XAML所以看起來很接近,但底層API、控制項周邊、專案結構、部署與packaging的思考方式、與Windows App SDK的相處方式都不同,把它當成可以從WPF輕鬆替換的目標很危險的圖。
u1["都用XAML所以看起來很接近"] --> u2["但不同的地方很多"]
u2 --> u3["底層API與控制項"]
u2 --> u4["結構與packaging"]
u2 --> u5["與SDK的相處方式"]
u5 -.-> u6["當成輕鬆替換的目標很危險"]
圖 13: 就算 XAML 一樣,WinUI 也不是可以從 WPF 輕鬆替換過去的目標。
5.3.2 選了 WinUI,散發的問題就會浮到前面
WinUI 3 應用程式 預設是 packaged。 另一方面,Windows App SDK 本身 packaged / unpackaged 兩種都支援。13142
這裡重要的是,
- 要怎麼散發
- 執行階段要怎麼安裝
- 需不需要 package identity
- 是公司內部散發、Store、MSIX,還是既有的 EXE / MSI 路線
這幾件事 最好提早決定。
只是,光說「提早確認」也很難知道要看什麼,所以把確認的內容寫在這裡。
- packaging:這個應用程式有沒有 package identity
- runtime:Windows App SDK 要用 framework-dependent,還是 self-contained 一起帶著走
flowchart TB
accTitle: 先決定的2個軸線
accDescr: 顯示WinUI的散發要先決定應用程式是否具有package identity的packaging軸線,以及Windows App SDK要用framework-dependent還是self-contained一起帶著走的runtime軸線這2個的圖。
h1["散發的設計"] --> h2["packaging的軸線"]
h1 --> h3["runtime的軸線"]
h2 -.-> h4["是否具有package identity"]
h3 -.-> h5["framework-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
確認的步驟,照這個順序在實務上最順。
- 從需求反推。 有沒有打算使用上面清單裡的功能。只要有一項,就需要 packaged 這一側。
- 看看能不能捨棄既有的安裝程式。 不想捨棄的話,答案就不是全面遷移到 MSIX,而是 指向外部位置的 packaged。既有的二進位檔擺放方式與更新機制都可以維持原樣,只補上 identity。13
- 在執行階段確認。 執行中的處理程序有沒有 identity,可以用
GetCurrentPackageFullName判定。沒有 identity 時會傳回APPMODEL_ERROR_NO_PACKAGE。反過來說,呼叫 Windows API 時出現E_ILLEGAL_METHOD_CALL或APPMODEL_ERROR_NO_PACKAGE,就是踩到 package identity 需求的訊號。13 - 在電腦端確認。 已安裝的套件可以用 PowerShell 的
Get-AppxPackage列出來。 - 最後決定 runtime。 想用 xcopy 或 zip 散發就選 self-contained,要上架 Store 的話,framework-dependent 是預設路線。15
WinForms / WPF 的散發同樣重要,但 WinUI 這一塊更容易浮到前景。新的 WinUI 3 應用程式 預設就是 packaged,什麼都沒決定的話,就會自動走上 MSIX 路線。13 本來以為只是在決定 UI,實際上決定的是散發策略——這是這個世界稍微麻煩的地方。
flowchart TB
accTitle: package identity的確認步驟
accDescr: 顯示從需求反推需要package identity的功能,看看能不能捨棄既有安裝程式,在執行階段與電腦端確認,最後決定runtime這5個步驟的確認流程的圖。
s1["1. 從需求反推"] --> s2["2. 看能不能捨棄安裝程式"]
s2 --> s3["3. 在執行階段確認"]
s3 --> s4["4. 在電腦端確認"]
s4 --> s5["5. 決定runtime"]
s2 -.-> s6["不想捨棄就用指向外部位置的packaged"]
s3 -.-> s7["用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 全面替換的承接對象,就需要理由與驗證。
flowchart TB
accTitle: 階段性遷移在當成主策略前先驗證
accDescr: 顯示一點一點混入WinUI的階段性遷移在構想上雖然吸引人,但FAQ指出除非準備好完全遷移否則多半用不了,XAML Islands也沒有給WPF或WinForms用的便利包裝,因此在當成主策略前應該先小規模驗證的圖。
v1["想一點一點混入WinUI"] --> v2["構想上很吸引人"]
v2 --> v3["FAQ的意思是以完全遷移為前提"]
v3 --> v4["沒有給WPF / WinForms用的包裝"]
v4 --> v5["當成主策略前先小規模驗證"]
圖 16: 「一點一點混入 WinUI」在當成主策略之前,要先小規模驗證。
6. 常見的判斷失誤
6.1 「因為最新所以選 WinUI」
這個理由很好懂,但相當危險。
選新技術的理由,最好用 是不是有非它不可才能得到的價值 來看。
- 現代的 Windows 體驗是不是產品價值
- 想不想直接了當地使用 Fluent
- 是不是新產品
- 能不能接受散發/維運的前提
這幾點如果是 yes,WinUI 就很有力。 反過來,如果只是「感覺有未來性」,成本的說明力道就很弱。
flowchart TB
accTitle: 不是「因為最新」而是用價值來選
accDescr: 顯示選新技術的理由應該看是不是有非它不可才能得到的價值,現代體驗是不是產品價值等問題若為yes則WinUI很有力,只有「感覺有未來性」則成本說明力道很弱的圖。
q0["選新技術的理由"] --> q1{"是否有非它不可才能得到的價值"}
q1 -->|"yes"| q2["WinUI很有力"]
q1 -->|"只有「感覺有未來性」"| q3["成本的說明力道很弱"]
圖 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 年後不改也能跑」的保證,所以 一開始就先決定要追隨到哪個版本 在實務上比較好。
flowchart TB
accTitle: 長期維護的讀法
accDescr: 顯示WPF與WinForms搭著每年的.NET發行加入功能,選了WinUI就要分別管理.NET與Windows App SDK的支援期限,因此要一開始就決定追隨到哪個版本的圖。
m1["WPF / WinForms"] --> m2["搭著.NET發行加入功能"]
m3["WinUI"] --> m4["分別管理SDK的期限"]
m2 --> m5["一開始就決定追隨到哪裡"]
m4 --> m5
圖 18: 長期維護要看更新是搭著什麼來的,並先決定追隨方針。
特別是業務應用程式,
- 既有資產
- 第三方控制項
- 畫面數量
- 報表與列印
- 設備介接
- 散發流程
這些常常比 UI 框架新不新更有份量。
6.4 「乾脆全面重寫」
全面重寫不是技術選型,而更接近 事業判斷。
如果已經有既有應用程式,最先該看的是這幾點。
- 真正困擾的是什麼
- 是 UI 的問題,還是架構的問題
- 相依 DLL / COM / OCX / 報表 / 散發,是不是才是真正的重擔
- 不把 UI 全部換掉,困擾的事情能不能解決
UI 重寫很華麗,成本也很華麗。 而且,就算外觀變新了,周邊的麻煩大致上還是會留著。
flowchart TB
accTitle: 全面重寫前要看的4個問題
accDescr: 顯示全面重寫不是技術選型而更接近事業判斷,要先看真正困擾的是什麼、是UI還是架構的問題、相依與散發是不是真正的重擔、不換UI能不能解決的圖。
r1["1. 真正困擾的是什麼"] --> r2["2. 是UI還是架構的問題"]
r2 --> r3["3. 相依與散發是不是重擔"]
r3 --> r4["4. 不換UI能不能解決"]
r4 -.-> r5["重寫的成本也很華麗"]
圖 19: 決定全面重寫之前,先用 4 個問題確認困擾的真面目。
6.5 「之後用 XAML Islands 總會有辦法」
這個期待可以理解。 但 不要一開始就把它當成救生艇 比較安全。1011
階段性遷移,最好先把
- 想嵌入的控制項是什麼
- 焦點、輸入、DPI、佈景主題會變成怎樣
- 那個宿主結構實際上會不會穩定
這幾點先小規模試過。
flowchart TB
accTitle: XAML Islands要先小規模試
accDescr: 顯示階段性遷移要先小規模試過想嵌入的控制項是什麼、焦點與輸入與DPI與佈景主題會變成怎樣、宿主結構會不會穩定,不要一開始就把它當成救生艇的圖。
p0["「之後總會有辦法」的期待"] --> p1["想嵌入的控制項是什麼"]
p0 --> p2["焦點・輸入・DPI・佈景主題"]
p0 --> p3["宿主結構會不會穩定"]
p1 --> p4["先小規模試"]
p2 --> p4
p3 --> p4
圖 20: XAML Islands 不要當成救生艇,先把 3 個點小規模試過。
7. 以既有應用程式為前提時的看法
這裡比新專案更重要,因為既有的部分才是關鍵。
7.1 已經有既有 WinForms 的話
先別急著跳到 WinUI,而是確認這幾點。
- 能不能靠向現行的 .NET
- 需不需要改成 64bit
- 能不能把 async / await、例外處理、設定、日誌整理一遍
- 能不能靠切分畫面或改成 UserControl 提高可維護性
- 能不能只用 Windows App SDK 補上需要的 Windows 功能
看起來是 WinForms 的問題,實際上只是
- 畫面和邏輯混在一起
- 執行緒邊界很草率
- 設定 / 檔案 / COM / DB 的職責全塞在一起
的情況並不少見。
這種時候,就算搬到 WinUI,問題也只是換個名字留下來而已。
flowchart TB
accTitle: 問題只是換個名字留下來
accDescr: 顯示看起來是WinForms的問題,實際上常常是畫面與邏輯混在一起、執行緒邊界草率、職責全塞在一起造成的,這種情況就算搬到WinUI問題也只是換個名字留下來的圖。
e1["看起來是WinForms的問題"] --> e2["其實是結構的問題"]
e2 --> e3["畫面與邏輯混在一起"]
e2 --> e4["草率的執行緒邊界"]
e2 --> e5["職責全塞在一起"]
e4 --> e6["搬到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 框架,而是先連相依邊界一起盤點 才對。
flowchart TB
accTitle: 連相依邊界一起盤點
accDescr: 顯示實務上沉重的多半是ActiveX與COM、報表與列印、原生DLL、安裝程式與更新等UI以外的部分,因此不要只看UI框架,先連相依邊界一起盤點的圖。
d1["ActiveX / COM interop"] --> d4["真正沉重的是UI以外"]
d2["報表・列印・Office介接"] --> d4
d3["安裝程式・權限・更新・簽署"] --> d4
d4 --> d5["先盤點相依邊界"]
d5 -.-> d6["只把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 摩擦比較少
flowchart TB
accTitle: 最後檢視的5個問題的流程
accDescr: 顯示依序套上既有資產大不大、現代體驗是不是必要、以標準表單為主還是需要表現力、散發與更新與維運能不能說明清楚這些問題來收斂選項的流程的圖。
f1{"既有資產大不大"} -->|"大"| f2["基本上維持既有系譜"]
f1 -->|"小・沒有"| f3{"現代體驗是不是必要"}
f3 -->|"必要"| f4["WinUI很有力"]
f3 -->|"沒到那個程度"| f5{"是否以標準表單為主"}
f5 -->|"是"| f6["WinForms"]
f5 -->|"表現力很重要"| f7["WPF"]
f2 -.-> f8["只是追加功能就先考慮SDK"]
f4 -.-> f9["提早敲定packaging與散發"]
圖 23: 猶豫時,依既有資產、體驗、畫面性質的順序套上問題來收斂。
用這 5 個問題就能收斂不少。 最後粗略地整理一下,大概是這樣。
- 快速做出來的公司內部表單 → WinForms
- 長期成長的 Windows 業務應用程式 → WPF
- 全新的現代 Windows 產品 UI → WinUI
- 活用既有資產,只把 Windows 功能現代化 → 現行框架 + Windows App SDK
9. 總結
WinForms、WPF、WinUI 的選型, 不是把它們照新舊排好然後挑最右邊的遊戲。
最先該看的是這 4 點。
- 既有資產在哪裡
- 畫面是以表單為主,還是以表現力為主
- Windows 風格的現代 UI 是不是產品需求
- 散發/更新/維運要怎麼跑
這 4 點一旦看清楚,方針大致就定了。
flowchart TB
accTitle: 總結的4個問題
accDescr: 顯示既有資產在哪裡、畫面是以表單為主還是以表現力為主、現代UI是不是產品需求、散發與更新與維運要怎麼跑這4點看清楚後方針大致就定了的圖。
n1["既有資產"] --> n5["方針大致就定了"]
n2["畫面的性質"] --> n5
n3["現代UI的需求"] --> n5
n4["散發與維運"] --> n5
圖 24: 4 個問題看清楚後,框架的方針大致就定了。
- 手上有大量既有 WinForms,就先繼續用 WinForms
- 手上有大量既有 WPF,就先繼續用 WPF
- 新專案以標準表單為主就選 WinForms
- 新專案是中~大規模的 Windows 業務應用程式就選 WPF
- 新專案的需求本身就是現代 Windows 體驗就選 WinUI
- 只是想用 Windows App SDK,就不要一口氣全部換成 WinUI
最想避免的是,
- 因為舊所以丟掉
- 因為新所以選它
- 抱著「途中總會有辦法」的心態開始
這 3 件事。
Windows 桌面是一個 資產、散發、維運、相依性 比外觀更有份量的世界。 所以,比起新鮮感,更重視與既有資產、散發、維運摩擦最少的選擇,在實務上才站得住腳。
10. 參考資料
-
Microsoft Learn, “WinUI 3 - Windows apps” / Microsoft Learn, “Modernize your desktop apps for Windows” ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Microsoft Learn, “什麼是 Windows Forms - Windows Forms” ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, “什麼是 Windows Presentation Foundation - WPF” ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, “What is Windows Forms Designer?” ↩ ↩2
-
Microsoft Learn, “Data binding overview - WPF” ↩ ↩2 ↩3
-
Microsoft Learn, “Commanding Overview - WPF” ↩ ↩2 ↩3
-
Microsoft Learn, “在 WPF 應用程式中使用 Windows 應用程式 SDK” ↩ ↩2 ↩3
-
Microsoft Learn, “Use the Windows App SDK in a Windows Forms (WinForms) app” ↩ ↩2 ↩3
-
Microsoft Learn, “Windows 開發者常見問題集” ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8 ↩9
-
Microsoft Learn, “Windows App SDK 1.4 release notes” / Microsoft Learn, “Windows App SDK” ↩ ↩2 ↩3
-
Microsoft Learn, “Windows data binding and MVVM” ↩
-
Microsoft Learn, “Packaging overview - Windows apps” / Microsoft Learn, “Grant package identity by packaging with external location” ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7
-
Microsoft Learn, “Quick start: Set up your environment and create a WinUI 3 project” ↩
-
Microsoft Learn, “Package and deploy Windows apps overview” ↩ ↩2
-
Microsoft Learn, “What’s new in WPF for .NET 9” ↩
-
Microsoft Learn, “What’s new in WinForms for .NET 9” ↩
-
Microsoft Learn, “Windows App SDK release channels” ↩
相關文章
共用相同標籤的最新文章。能以相近的主題延伸理解。
委外・委託開發 Windows 應用程式前該整理的事項
在委外・委託開發 Windows 應用程式之前,整理既有軟體改版、設備整合、COM/ActiveX、發布與更新、維護等應留意的重點。
「沒有回應」的真面目 ── Windows 如何判定應用程式當住,以及不卡住的設計
Windows 的「沒有回應」是作業系統判定視窗 5 秒未取出訊息後,換成幽靈視窗的機制。本文涵蓋該判定的內部、無回應的經典原因、把重工作移出 UI 執行緒的設計,以及調查無回應的程序。
WinForms / WPF 應用程式的 CI/CD 實務 ── 用 GitHub Actions 把從建置到簽章・發布全部自動化
本文整理用 GitHub Actions 為 WinForms / WPF 應用程式建置 CI/CD 的實務指南,內容涵蓋在 windows-latest 上進行建置+測試的最小 YAML、以標籤驅動的版本編號、透過 signtool 整合簽章,以及依 MSI/MSIX/C...
Windows 應用程式的工作列通知區常駐與 Toast 通知 —— NotifyIcon 的陷阱與 AppNotification 的選型
本文整理將業務用 Windows 應用程式常駐於工作列通知區,並透過 Toast 通知告知使用者的實作要點。內容涵蓋 NotifyIcon 的正確用法與「關閉後仍留在通知區」的設計、檔案總管重新啟動時的重新註冊、三種 Toast API(Windows App SDK Ap...
在桌面應用程式使用 .NET Generic Host 與 BackgroundService 的理由
為了在 Windows 工具與常駐型應用程式中梳理啟動、定期處理、終止處理、日誌、設定與 DI,本文整理 Generic Host 與 BackgroundService 該怎麼用。
相關主題
與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。
Windows 技術主題
彙整 KomuraSoft LLC 關於 Windows 開發、故障調查與既有資產活用文章的主題中心。
UI 執行緒 & 計時器
整理 WPF / WinForms UI 執行緒、非同步流程、Dispatcher 使用、計時器判斷的主題頁面。
與本主題相關的服務
本文連結到以下服務頁面,歡迎從最接近的入口查看。
Windows 應用程式開發
WinForms、WPF、WinUI 的選型,直接關係到 Windows 桌面應用程式的新專案開發,以及既有資產要如何延續使用的方針。
技術諮詢 & 設計審查
適合把既有資產、Windows App SDK、散發設計、UI 表現以至 MVVM 文化都一起納入,梳理哪一個選擇摩擦最少的階段。
常見問題
整理諮詢這個主題時常見的問題。
- 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 全面遷移並不是必要條件。