title | author | date | CreateTime | categories |
win10 uwp xaml 相容多個版本條件編譯 | lindexi | 2019-5-21 11:19:3 +0800 | 2018-03-18 15:37:54 +0800 | Win10 UWP |
在 UWP 開發有一個坑就是存在很多SDK的版本,同時不同的系統帶的SDK是不相同的,還好現在高版本的系統是可以支援低版本的程式的。為了做到盡可能相容,程式需要用到足夠低的 SDK 版本,但是又存在很多新版本特性非常好用,那麼如何在使用者端判斷目前的系統是哪個版本對應可以使用新版本的特性?當然這個代碼在背景代碼一點都不難,但是界面呢?本文告訴大家如何設定 xaml 的條件編譯
如果隻需要在 cs 代碼判斷版本,那麼可以使用星期大神的代碼,請看UWP 判斷系統版本
public class VersionsHelper
{
public static Boolean Windows10Build10240 => ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 1, 0);
public static Boolean Windows10Build10586 => ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 2, 0);
public static Boolean Windows10Build14393 => ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 3, 0);
public static Boolean Windows10Build15063 => ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 4, 0);
public static Boolean Windows10Build16299 => ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 5, 0);
}
但是如果是在 xaml 應該怎麼寫? 我需要使用 16299 的功能,但是我需要讓程式可以在 15063 運作,那麼這時就需要 uwp xmal 條件編譯。
使用的方法很簡單,不過條件編譯不是和 cs 代碼使用
#if
的方式。
這裡的 xaml 條件編譯(Conditional XAML)就是 ApiInformation.IsApiContractPresent 提供的标記。
因為這個标記稍微有些複雜,是以我先寫代碼給大家看
xmlns:contract5NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,5)"
xmlns:contract5Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)"
<TextBlock Margin="200,200,0,0" contract5NotPresent:Text="以前的系統"
contract5Present:Text="最新的系統"></TextBlock>

因為xaml條件編譯是在創意者更新 15063 支援的,是以需要先右擊屬性,設定最低版本為 15063,然後才可以編譯
因為我的系統是 16299 是以運作就是顯示最新的系統,如果是在 15063 的系統運作,因為我自己沒運作,是以運作顯示的我也不知道。
下面讓我來告訴大家是如何寫的。
首先在命名定義一個變量,這個變量是可以随意寫的,我是直接抄微軟代碼,是以寫為
contract5Present
,他的值就是 http://schemas.microsoft.com/winfx/2006/xaml/presentation ,因為微軟支援在最後面添加函數,是以加上函數
IsApiContractPresent
就是這樣寫
xmlns:contract5Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)"
那麼需要來告訴大家
IsApiContractPresent
是做什麼?
如果大家有打開 UWP 判斷系統版本那麼會發現判斷系統的方法是通過最後的數字。
對應的數字
- 1:10240
- 2:10586
- 3:14393
- 4:15063
- 5:16299
如果在運作比數字低的版本,會傳回true,例如 在運作 15063 的系統,可以看到下面的代碼傳回的值
- IsApiContractPresent(Windows.Foundation.UniversalApiContract, 5) = false // 不屬于 16299
- IsApiContractPresent(Windows.Foundation.UniversalApiContract, 4) = true // 屬于 15063
- IsApiContractPresent(Windows.Foundation.UniversalApiContract, 3) = true // 屬于 14393
- IsApiContractPresent(Windows.Foundation.UniversalApiContract, 2) = true // 屬于 10586
- IsApiContractPresent(Windows.Foundation.UniversalApiContract, 1) = true // 屬于 10240
是的,如果運作在 16299 版本的系統上,那麼後面寫 12345 都是傳回true 是以在最高傳回 true 的版本就是目前系統可以支援的版本。在調用 IsApiContractPresent 方法,如果傳回 true 那麼設定的屬性才可以。如果傳回 false 那麼在運作就不會有設定。
但是不能這樣寫代碼
<TextBlock Text="Hello, World" contract5Present:Text="Hello, Conditional XAML"/>
如果需要判斷在 16299 就設定這個屬性,而在非 16299 就不設定這個屬性,就需要使用
IsApiContractNotPresent
對比一下,如果在 15063 的系統運作程式,那麼下面代碼就是這個值
- IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 5) = true
- IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 4) = false
- IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 3) = false
- IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 2) = false
- IsApiContractNotPresent(Windows.Foundation.UniversalApiContract, 1) = false
IsApiContractPresent 是在目前系統和低于目前系統傳回 true ,IsApiContractNotPresent 是在非目前系統和不低于目前系統傳回 true
是以使用
IsApiContractPresent
和
IsApiContractNotPresent
可以設定目前使用的是那個版本
例如使用下面的代碼,用到了 RevealBorderBrush 這個新功能
<RevealBorderBrush x:Key="KilqpdiHbmgvaz" TargetTheme="Light" Color="#08000000" FallbackColor="{ThemeResource SystemAccentColor}"/>
這時編譯直接說不可以使用
那麼使用條件編譯就可以讓他編譯通過
<contract5Present:RevealBorderBrush x:Key="KilqpdiHbmgvaz" TargetTheme="Light" Color="#08000000" FallbackColor="{ThemeResource SystemAccentColor}"/>
這時因為垃圾微軟的 VisualStudio 的開發者不知道已經有這個,是以就告訴你錯誤,不要去理他,直接運作。
全部代碼
<Page.Resources>
<contract5Present:RevealBorderBrush x:Key="KilqpdiHbmgvaz" TargetTheme="Light" Color="#08000000" FallbackColor="{ThemeResource SystemAccentColor}" />
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid Margin="200,200,20,20"
contract5Present:Background="{StaticResource KilqpdiHbmgvaz}"
contract5NotPresent:Background="#FF565656" />
</Grid>
實際上就是 contract5Present 支援設定屬性或控件,可以使用 contract5Present 用新的系統的控件。
是以也可以使用下面的方法,例如在 16299 才有的 ColorPicker ,如果希望程式在 15063 使用,在以前的系統使用 ComboBox ,那麼就可以使用下面的代碼
<contract5Present:ColorPicker />
<contract5NotPresent:ComboBox />
這樣在新的系統就會使用 ColorPicker ,在以前的系統就會使用 ComboBox
如果在一個綁定一個使用了 contract5Present 的控件,那麼在綁定的屬性需要使用 contract5Present 不然微軟的 VisualStudio 不然讓你使用。
需要告訴大家,感覺說的 VisualStudio 在 Xaml 報告的錯誤,實際上這是Resharper的
如果覺得自己需要寫的軟體的版本比支援條件編譯的版本還低,而且也不想寫太多條件編譯,請看使用 Microsoft.UI.Xaml 解決 UWP 控件和對老版本 Windows 10 的相容性問題 - walterlv