条件付きXAMLの書き方
文法
条件付き名前空間の書式は、次のようになります。
xmlns:{条件付き名前空間名}="http://schemas.microsoft.com/winfx/2006/xaml/presentation?{条件式}" ただし、{条件式}は次のいずれか 肯定式: IsApiContractPresent({コントラクト識別名}, {コントラクト バージョン番号}) IsTypePresent({UIコントロールの型名}) IsPropertyPresent({UIコントロールの型名},{プロパティ名}) 否定式: IsApiContractNotPresent({コントラクト識別名}, {コントラクト バージョン番号}) IsTypeNotPresent({UIコントロールの型名}) IsPropertyNotPresent({UIコントロールの型名},{プロパティ名})
上で、コントラクト識別名というのは正式には「APIコントラクト」(API contract)と呼ぶようです。一般的にはWindows.Foundation.UniversalApiContract
(UWPの共通API)だけで事足りるでしょう。そのほかにも、Windows.ApplicationModel.Calls.CallsVoipContract
やデスクトップ エクステンションのWindows.ApplicationModel.Activation.ActivatedEventsContract
などなど、多数のコントラクトが定義されています。APIコントラクトの一覧は、Device Family Extension SDKs and API contractsをご覧ください。
一般的に使うWindows.Foundation.UniversalApiContract
コントラクトのバージョン番号と、Windows 10のバージョン/ビルドの関係を次の表に示しておきます。
コントラクト番号 | Windows 10のバージョン/ビルド |
---|---|
1 | 1507/10240 |
2 | 1511/10586 |
3 | 1607/14393 |
4 | 1703/15063 |
5 | 1709/16299 |
先に示した例では、contract5Present
というのは1709/16299以上の場合、contract5NotPresent
は1709/16299未満の場合という意味になります。
また、書式説明中の「UIコントロールの型名」というのは、名前空間を付けたクラス名です。後述の例を見ていただくと分かるかと思います。
IDEサポート
条件付き名前空間の記述は、長くて面倒ですね。Visual Studio 2017は、コントラクトによる条件付き名前空間を自動生成してくれます。
XAMLに、プロジェクトに指定した最小バージョンのWindows 10では利用できないUIコントロールを記述すると、次の画像のように警告(青い波線)が出るとともに、「電球マーク」が出てきます(表示されないときは[Ctrl]+[.])。電球マークを展開すると条件付き名前空間の提案が表示されるので、[Enter]キーを押すとその条件付き名前空間がPageタグに挿入されます。
自動生成される条件付き名前空間は肯定式だけですが、否定式も必要なときはコピー&ペーストしてNot
を書き加えてやればよいです(条件付き名前空間名と条件式の2箇所)。
最もよく使うと思われるコントラクトによる条件付きXAMLは、このようにIDEがサポートしてくれます。上で条件付き名前空間の書式を説明しましたが、きっちり覚えていなくてもそんなに困ることはないでしょう。
Windows 10のバージョンで使い分ける例
コントラクト(Windows 10のバージョン)による条件付き名前空間をプロパティに適用する例は、最初に示しました(アクリル効果の有無)。今度は、UIコントロールそのものの有無を切り分けてみましょう(⇒Page2.xaml)。
ColorPicker
コントロールは1709/16299で導入された新しいUIコントロールです。それ以前のWindows 10で実行されたときにはColorPicker
コントロールの代わりにComboBox
コントロールを表示するようにするには、次のXAMLのようにします。
<Page ……省略…… xmlns:contract5Present="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractPresent(Windows.Foundation.UniversalApiContract,5)" xmlns:contract5NotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsApiContractNotPresent(Windows.Foundation.UniversalApiContract,5)" > ……省略…… <contract5Present:ColorPicker x:Name="colorPicker" Grid.Column="1" VerticalAlignment="Center" Color="{x:Bind SampleData.SampleColor, Mode=TwoWay}"/> <contract5NotPresent:ComboBox x:Name="colorComboBox" PlaceholderText="Pick a color" Grid.Column="1" VerticalAlignment="Center" SelectionChanged="colorComboBox_SelectionChanged"> ……省略…… </contract5NotPresent:ComboBox> ……省略……
条件付き名前空間の定義は、最初の例と同じです。条件付き名前空間の適用先が、この例ではUIコントロールになっています。UWP APIのコントラクトが5(すなわち、Windows 10 1709/16299)またはそれ以降で実行されたときは、contract5Present
を付けたColorPicker
コントロールがインスタンス化されます。コントラクトが5未満のWindows 10で実行されたときは、contract5NotPresent
を付けたComboBox
コントロールのインスタンスが生成されるのです(次の画像)。
UIコントロールの有無で使い分ける例
最後は、IsTypePresent
/IsTypeNotPresent
を使ってUIコントロールの有無でXAMLを使い分ける例です(⇒Page3.xaml)。
先ほどのColorPicker
コントロールの例は、ColorPicker
コントロール自体がサポートされているかどうかで切り分けても同じ結果が得られます。IsTypePresent
/IsTypeNotPresent
を使って、次のXAMLのように書けます。
<Page ……省略…… xmlns:isColorPickerPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsTypePresent(Windows.UI.Xaml.Controls.ColorPicker)" xmlns:isColorPickerNotPresent="http://schemas.microsoft.com/winfx/2006/xaml/presentation?IsTypeNotPresent(Windows.UI.Xaml.Controls.ColorPicker)" > ……省略…… <isColorPickerPresent:ColorPicker x:Name="colorPicker" Grid.Column="1" VerticalAlignment="Center" Color="{x:Bind SampleData.SampleColor, Mode=TwoWay}" /> <isColorPickerNotPresent:ComboBox x:Name="colorComboBox" PlaceholderText="Pick a color" Grid.Column="1" VerticalAlignment="Center" SelectionChanged="colorComboBox_SelectionChanged"> ……省略…… </isColorPickerNotPresent:ComboBox> ……省略……
実行結果の画像は省略しますが、先ほどと同様になります。
ColorPicker
コントロールが使えるプラットフォーム(Windows 10 1709/16299またはそれ以降)では条件付き名前空間isColorPickerPresent
が有効になるので、ColorPicker
コントロールの方だけがインスタンス化されます。ColorPicker
コントロールが使えないプラットフォームでは、逆にComboBox
コントロールだけがインスタンス化されるというわけです。
なお、現時点(Visual Studio 2017 15.5)では、コントラクトによる条件付き名前空間ほどはIDEのサポートが充実していません。将来はサポートされるでしょうが、今のところは型による条件付き名前空間を自動生成してくれないようです。また、XAMLプレビューでは型による条件付き名前空間は無視され、XAMLエディターでは警告が出てしまうようです。
まとめ
条件付きXAMLによって、新しいWindows 10で実行されているときだけ新しい機能(UIコントロールやプロパティ)を使い分けるということが、XAMLだけで簡単に記述できるようになりました。
これからは、「以前のWindows 10もサポートしなけりゃならないから、新機能はちょっと……」とあきらめなくても良いのです。新しいWindows 10を使っているユーザーには、新しいUXを提供していきましょう!