1. 程式人生 > >使用 Microsoft.UI.Xaml 解決 UWP 控制元件和對老版本 Windows 10 的相容性問題

使用 Microsoft.UI.Xaml 解決 UWP 控制元件和對老版本 Windows 10 的相容性問題

原文 使用 Microsoft.UI.Xaml 解決 UWP 控制元件和對老版本 Windows 10 的相容性問題

雖然微軟宣稱 Windows 10 將是最後一個 Windows 版本,但由於年代跨越實在太久遠,相容性依然是避不開的問題。Microsoft.UI.Xaml 的預覽版現已推出,旨在解決 UWP UI 控制元件在各個不同版本 Windows 上的相容性問題。

本文將簡單瞭解一下 Microsoft.UI.Xaml 庫,然後實際看看它的效果。


本文內容

Windows 10 的相容性問題

在建立 UWP 應用的時候,我們可以選擇目標版本和最低版本。目標版本決定了我們能使用的最新 API,最低版本決定了我們需要支援的最低版本的 Windows 10。

選擇目標版本和最低版本
▲ 圖中目標版本為 17134,最低版本為 14393。事實上,目標版本必須是 17134,最低只能支援到 14393。

然而,每一次新版本 Windows 10 的推出,都帶來大量新的開發 API。可以去官方文件 Choose a UWP version - UWP app developer - Microsoft Docs 瞭解各個版本 Windows 10 新增的功能簡介。

微軟在 Windows 10 16299 版本帶來了 XAML 條件編譯,用以在 XAML 中相容不同版本的 Windows 10,然而這意味著必須選擇 16299 作為最低 API 版本才能正常使用此功能。當然,XAML 條件編譯還是帶來了不少方便的特性呢,閱讀 win10 uwp xaml 相容多個版本條件編譯 - 林德熙 可以瞭解 XAML 條件編譯的使用方法,順便收穫一隻貓。

Windows 10 也在各個版本新增了一些控制元件。那麼問題來了,要支援最低版本就不能使用新控制元件。Windows 10 又不像 iOS 那樣更新率高,意味著根本不能使用新控制元件進行開發。

NavigationView

Microsoft.UI.Xaml 庫

於是微軟就推出了在 上推出了 NuGet 包 [Microsoft.UI.Xaml](https://www.nuget.org/packages/Microsoft.UI.Xaml)。

使用此包,你需要將 UWP 的 目標版本設為 17134,支援的 最低版本只能到 14393,不能更低。

官方對此包的描述為:

This package provides backward-compatible versions of Windows UI features including UWP XAML controls, and Fluent styles and materials. It is part of the Windows UI Library.

即提供各種 Windows UI 功能的向後相容性,包括 UWP XAML 控制元件、Fluent 流暢設計樣式和畫刷。當然,不支援亞克力效果的系統版本雖然畫刷能用,不崩潰,但也沒有效果的。

安裝 Microsoft.UI.Xaml

Microsoft.UI.Xaml 的上手方法

安裝 Microsoft.UI.Xaml 後,Visual Studio 會自動開啟 readme.txt 檔案提示我們用法:

Thanks for installing the WinUI nuget package! Don’t forget to add this to your app.xaml:

<Application.Resources>
    <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
</Application.Resources>

See http://aka.ms/winui for more information.

即我們需要在 App.xaml 檔案中新增 <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/> 作為應用程式的全域性資源。不過,官方文件 Getting started with the Windows UI library 中有對此更詳細的描述。

如果我們是新 UWP 程式,這樣寫是沒問題的:

<Application>
    <Application.Resources>
        <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/> </Application.Resources> </Application> 

但如果基於原有的程式進行相容性改造,可能原 Application 中已經有資源了,就必須換一種寫法:

<Application>
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application> 

當然,以上這種改造在各種 XAML 上的行為都是一樣的,比如我在 StackOverflow 上回答的問題 Use ResourceDictionary with other Styles in WPF 也是這樣的改法,其中說明了必須這樣修改的原因。

不過沒有結束,在需要使用到新版本 Windows 10 控制元件的 XAML 檔案中,需要新增名稱空間字首:

xmlns:controls="using:Microsoft.UI.Xaml.Controls"

這樣才能在 XAML 中使用 Microsoft.UI.Xaml 庫中的新控制元件:

<Grid>
    <controls:NavigationView x:Name="WalterlvDemoView"> <controls:NavigationView.MenuItems> <ListViewItem Content="Home" /> <ListViewItem Content="Demo" /> <ListViewItem Content="About" /> <ListViewItem Content="https://walterlv.github.io/" /> </controls:NavigationView.MenuItems> </controls:NavigationView> </Grid> 

還記得本文開頭那張 Visual Studio 的相容性提示圖片嗎?使用了 Microsoft.UI.Xaml 庫之後,不會再有提示了。這不是欺騙,是真的具備了對早期系統的相容性。

於是,一些廣泛使用的 UWP 應用終於不用各種自己寫控制元件來相容低版本的 Windows 10 了。

當然除了在 XAML 中,也可以在 C# 程式碼中使用庫中的新 API。

解決意料之外的錯誤

一切可以那麼順利?不一定,你可能在剛剛把 <XamlControlsResources /> 加入之後,就會發現程式啟動即崩潰了……

然後提示:

System.Runtime.InteropServices.COMException
HResult=0x80004005
Message=Error HRESULT E_FAIL has been returned from a call to a COM component.
Source= StackTrace:

啟動異常

不得不說,微軟再一次把內部錯誤暴露了出去。實際的錯誤原因是 —— 目標 SDK 需要設定為 17134—— 這是必須的!

設定為 17134

當然,這個版本號並不是跟隨系統的,而是跟隨 Microsoft.UI.Xaml 庫的。庫如果更新有新系統的控制元件,那麼你更新庫之後就需要再次更新目標 SDK 版本了。

本文會經常更新,請閱讀原文: https://walterlv.com/post/getting-started-with-microsoft-ui-xaml.html ,以避免陳舊錯誤知識的誤導,同時有更好的閱讀體驗。