到这里为止都和预期的一样,我之后还尝试了将 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)。而且 WinUI 2 中代码的命名空间以 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 内存 GPUWPF .NET Framework 4.8 12 60 76
WPF .NET 5.0 12 85 72
UWP 3 28 36
WinUI 5 65 95