1. 什麼是 WinUI 3 在微軟 Build 2020 開發者大會上,WinUI 團隊宣佈可公開預覽的 WinUI 3 Preview 1,它讓開發人員可以在 Win32 中使用 WinUI。WinUI 3 Preview 1 包含新的 VisualStudio 項目模板,可以創建面向 .NET ...
1. 什麼是 WinUI 3
在微軟 Build 2020 開發者大會上,WinUI 團隊宣佈可公開預覽的 WinUI 3 Preview 1,它讓開發人員可以在 Win32 中使用 WinUI。WinUI 3 Preview 1 包含新的 VisualStudio 項目模板,可以創建面向 .NET 5 的 C# 和 C++/Win32 項目。從技術上講,WinUI 3 將 UWP 的 XAML、Composition 和 Input 層分離,並通過NuGet將它們獨立分發給針對Windows 10 版本 1803 及更高版本的 Win32 應用。
WinUI 3 適用於 Win32 和 UWP,這篇文章主要討論 Win32 的情況。
2. 理解 WinUI 3
以前我們總是抱怨 WPF 多年都不提供新的主題,不提供新的控制項,性能又沒提升。現在微軟索性把什麼都是新的 WinUI 3 提供給桌面開發,沒 WPF 什麼事了。
簡單來說,UWP 的開發體驗不好(關於這個話題真是一言難盡),而且出了 Bug 還必須等待下半年的 Windows 更新進行修複,但微軟的開發人員專心給 UWP 的 UI 層加各種功能;.NET Core 更新很快,但很少人有興趣有動力給陳舊的 WPF 的 UI 層進行大幅度的改進。於是 WinUI 將 UWP 的 UI 層從 Windows SDK 的其它部分分離,並將從 Windows 轉移到 Nuget。現在建一個 C++ 或 C#(.NET 5) 程式,再從 Nuget 上裝個 WinUI 3 的包套個 UI 層,一個基於 Fluent Design,觸摸友好,性能無與倫比的應用程式就誕生了。
上圖列舉了 WinUI 3 和其他平臺對比的部分特性,除此之外 WinUI 3 還有很多好處,例如開源、更新更快、更新不與系統版本綁定等,更詳細的內容還是看微軟自己怎麼宣傳吧:
WinUI - The modern native UI platform of Windows.
不過要用上 WinUI 3 還要等一年半載。下麵是微軟給出的發佈路線圖,目前我們也只能用 Preview 版嘗嘗鮮。
3. 試玩WinUI 3
要試玩 WinUI 3 首先要有 Windows 10 1803 以上版本的電腦(WinUI 3 最低支持1803),然後還需要使用 Visual Studio 2019 16.7 以上版本(目前只能安裝預覽版)。安裝 Visual Studio 時要把以下工作負載全都選上:
- .NET 桌面開發
- 通用 Windows 平臺開發
- 使用 C++ 的桌面開發
- 適用於通用 Windows 平臺負載的 C++(V142) 通用 Windows 平臺工具可選組件
當然 .NET 5.0 也要裝上。
然後在 https://aka.ms/winui3/previewdownload 下載並安裝 WinUI 3 Project Templates 擴展,這樣才可以在 Visual Studio 創建 WinUI 的項目。
可選 C++ 或 C# ,這裡我選擇了 C# 的“Blank App, Packaged
(WinUI in Desktop)”項目,並選擇了對應的 Windows 平臺:
項目創建後 Visual Studio 生成了兩個項目。第一個包含應用的代碼,代碼結構基本和 UWP 一樣,只是少了用於打包應用的 Package.appxmanifest 和一些圖片。從依賴項里可以看到項目已經安裝了 Microsoft.WinUI 3 的包。從項目屬性里可以看到這就是個 .NET 5 的項目。
Visual Studio 生成的第二個項目是一個 Windows 應用程式打包項目,該項目經配置後可將應用生成為適合部署的 MSIX 程式包。 也就是說 UWP 項目中用於打包的部分被獨立出來了。這個項目還應該是解決方案的啟動項目。運行這個項目後創建的應用會添加到開始菜單中,這點也和UWP一樣。
到這裡為止都和預期的一樣,我之後還嘗試了將 UWP 應用移植到 WinUI ,基本上只需要將 Windows.UI
命名空間改為 Microsoft.UI
就可以了,XAML 和 C# 代碼完全不用變。只可惜目前 WinUI 還很簡陋,Win2D、Community Toolkit 等微軟自己發佈的 UWP 包都還沒有 WinUI 版本。而且沒有設計視圖,XAML 視圖也沒有智能感知,現在想要用 WinUI做些什麼有趣的項目會很困難。不過從目前的移植難度上來看,將來正式發佈後應該可以完整地將 UWP 的 UI 的開發經驗運用在 WinUI 上。
4. 和 WPF 及 UWP 進行對比
既然 WinUI 3 開發模式和 WPF 及 UWP 都很像,我當然對它們之間的對比很感興趣。
命名
首先說說命名,“WinUI” 光這個名字就 Win 了。 “UWP” 太高雅,我敢打賭國內有些 UWP 的開發(例如我)都不能好好地把 UWP 的全稱拼出來;“WPF” 好些,但 WPF 的含義也讓人很疑惑。而 Windows UI 簡稱 WinUI ,意義和發音都很清晰明確。不過這三個都比很多人都不會讀的 “Xamarin” 強多了。
可是有了 WinUI 3 ,就會有人問“那 WinUI 2 呢?”WinUI 2是一個 UWP 的控制項庫,當然的只能用在 UWP 上。這就很尷尬了,WinUI 的 3 和 2 根本不是同一個概念,實在很容易讓人混淆,說不定以後會把尾碼的 3
去掉(我這篇文章就常常懶得理寫這個3
)。而且 UWP 中代碼的命名空間以 Windows.UI
開頭,在 WinUI 3 中則 Microsoft.UI
,按著 Office 365 改名為 Microsoft 365、Bind Ads 改名為 Microsoft Advertising 這些經驗,該不會以後 WinUI 可能改名為 Microsoft UI ,簡稱 MiUI 吧?
許可權
許可權方面是 WinUI 的一個亮點,因為它本質上就是個 Win32 程式,可以放開手腳隨便來。相對的 UWP 有很嚴格的許可權限制,開發 UWP 時常常會感到綁手綁腳。例如下麵這段代碼,大部分 WPF 開發者都難以想象只是最小化 UWP 程式而已,它就不能好好運行了:
int count = 0;
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += (s, e) =>
{
myButton.Content = count++;
};
timer.Start();
UWP 的生命周期如上圖,當 UWP 處於 background 運行或 suspended 狀態時應用基本處於暫停狀態,也也不會處理UI功能。我明白這是 UWP 為了省電、安全等原因才這樣設計,但對開發人員來說真的太不方便。而 WinUI 應用基本上就是個 Win32 應用,目前看來不會有這些坑。
開發體驗
說起開發體驗,WPF 好歹還算正常,Visual Studio 的設計視圖運行正常,編譯起來也快。UWP 編譯很慢,設計視圖經常出問題,Blend 也時好時壞把設計師都氣跑了。就算完全按著官方的文檔完成一個 UWP App,甚至一行代碼都不改,發佈到商店後還是有可能崩潰。而對於應用商店,真是千言萬語彙聚成一個草花頭。
現在 WinUI 的 XAML 視圖連智能感知都沒有,也沒有設計視圖,實在沒法談開發體驗。很難猜測正式發佈的時候會怎麼樣,希望至少和WPF保持一致吧。
性能
WPF 總是給人“慢”的印象,除了因為在它剛出來的時候(10年前)電腦性能不夠導致留下了刻板印象,還有一個主要原因是:它真的很慢。
UWP 的 XAML 有很優秀的性能表現,除此之外為了照顧已經不存在的 Windows Phone 的貧弱性能,很多控制項模版都經過精心設計並大幅簡化。
為了驗證 WinUI 的性能我寫了下麵這些代碼,然後分別移植到 WPF .Net Framework 4.8、WPF .NET 5、UWP、WinUI(WPF 和 UWP/WinUI 的代碼稍微有一點不同):
for (int i = 0; i < 50; i++)
{
var rectangle = new Rectangle
{
Height = 500,
Width = 500,
Opacity = ((double)i + 40) / 100d,
RadiusX = 108,
RadiusY = 98,
StrokeThickness = 3,
Stroke = new SolidColorBrush(Color.FromArgb(255, 75, 75, (byte)(i * 250d / 50d))),
RenderTransformOrigin = new Point(0.5, 0.5)
};
Root.Children.Add(rectangle);
var angle = i * 360d / 50d;
var transform = new RotateTransform
{
Angle = angle
};
rectangle.RenderTransform = transform;
var storyboard = new Storyboard();
storyboard.Children.Add(new DoubleAnimation { Duration = TimeSpan.FromSeconds(1), From = angle, To = angle + 360 });
Storyboard.SetTarget(storyboard, transform);
Storyboard.SetTargetProperty(storyboard, "Angle");
storyboard.RepeatBehavior = RepeatBehavior.Forever;
storyboard.Begin();
}
上面這段代碼是讓50個矩形旋轉,十分考驗 WPF 的性能。結果可以說出乎意料。
CPU | 記憶體 | GPU | |
---|---|---|---|
WPF .NET Framework 4.8 | 12 | 60 | 76 |
WPF .NET 5.0 | 12 | 85 | 72 |
UWP | 3 | 28 | 36 |
WinUI | 5 | 65 | 95 |
我的環境是 i7-6820HQ 及集成顯卡。WPF 平臺占用 70 多%的 GPU,這我大致能猜到。UWP 十分流暢,GPU 只占用 WPF 的一半,CPU 和 記憶體都有出色表現,不過我還以為會更低的。
WinUI 這個濃眉大眼的我真的萬萬沒想到,不僅掉幀明顯,還占用了幾乎 100% GPU,也就是說它連這麼簡單的代碼都跑不起來。()順便一提,將測試代碼中旋轉的矩形減少為10個,WPF 的程式占用 32% GPU,而 WinUI 占用 70 多%。)
從上面的數據基本可以說明,WinUI 離設計目標還十分遙遠,畢竟是預覽版,還有一年半載可以慢慢優化。
5. 結語
總的來說微軟雄心勃勃,可是現在拿出來的 WinUI 預覽版還差得太遠,功能未完善,性能不及預期。我覺得大致方向沒錯,WinUI 對 C++、WPF、UWP 開發者都是個新的工具新的機遇,可以關註一下。
6. Q & A
Windows 7 怎麼辦?
按微軟公佈的路線圖,再包括跳票等因素,等 WinUI 真正可用時 Windows 7 已停止更新很久,到時 Windows 7 的占有率可能已經下降到開發者不會關心的程度。
基於 .NET Core 的 Wpf 還是 WinUI?
假使不想花精力將現有項目遷移到 WinUI,或者對來自 UWP 的 WinUI 沒信心,又或者捨不得 Windows 7 的用戶,並且對觸摸沒需求,當然可以繼續選用 WPF,基於 .NET Core 的 WPF 會是個很好的選擇。
MAUI 還是 WinUI ?
MAUI 還在很遙遠的將來(2021年11月),我沒試玩過,所以不好評價。如果有跨平臺需求當然只能選 MAUI,如果 WinUI 團隊技高一籌實現了 MAUI 難以企及的超高性能,那就選 WinUI。不過 MAUI 這個名字太過普通/普遍,可能會被逼著改名吧。
那 UWP 呢?
許可權受限的 UWP 可以說是人畜無害,對用戶來說可能也是個不錯的選擇。而且 UWP 還支持 Xbox 和 Hololens 等平臺,目前看來還是有它的市場。
Winforms 呢?
人只有忘卻了過去,才能好好活著。
WinUI 有未來嗎?
我做了好多年 Silverlight 開發,買了5、6部 Windows Phone 手機,寫了幾十篇 UWP 文章,根據我豐富的經驗,我可以肯定 WinUI 是有未來的。
8. 參考
WinUI - The modern native UI platform of Windows.
Introducing WinUI 3 Preview 1 - Windows Developer Blog
Get started with WinUI 3 for desktop apps Microsoft Docs
GitHub - microsoft_microsoft-ui-xaml
WinUI 3.0_ The future of Windows controls