XAML のテーマ リソースは、アクティブなシステム テーマに応じて異なる値を適用するリソースのセットです。 XAML フレームワークでサポートされるテーマは 3 つあります。"Light"、"Dark"、"HighContrast" です。
前提条件: このトピックでは、 ResourceDictionary および XAML リソース参照を読み取っていることを前提としています。
テーマ リソース v. 静的リソース
既存の XAML リソース ディクショナリから XAML リソースを参照できる XAML マークアップ拡張には、 {StaticResource} マークアップ拡張 と {ThemeResource} マークアップ拡張の 2 つがあります。
{ThemeResource} マークアップ拡張機能の評価は、アプリが読み込まれた後、実行時にテーマが変更されるたびに発生します。 これは通常、ユーザーがデバイスの設定を変更した結果、または現在のテーマを変更するアプリ内のプログラムによる変更の結果です。
これに対し、 {StaticResource} マークアップ拡張 は、XAML がアプリによって最初に読み込まれたときにのみ評価されます。 更新されません。 これは、XAML での検索と置換に似ていますが、アプリの起動時に実際のランタイム値に置き換えられます。
リソース ディクショナリ構造のテーマ リソース
各テーマ リソースは、XAML ファイル themeresources.xaml の一部です。 設計上、themeresources.xaml は、Windows ソフトウェア開発キット (SDK) インストールの \(Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK バージョン>\Generic フォルダーにあります。 themeresources.xaml のリソース ディクショナリは、同じディレクトリの generic.xaml でも再現されます。
Windows ランタイムでは、ランタイム検索にこれらの物理ファイルは使用されません。 そのため、これらは特に DesignTime フォルダー内にあり、既定ではアプリにコピーされません。 代わりに、これらのリソース ディクショナリは Windows ランタイム自体の一部としてメモリ内に存在し、アプリの XAML リソースからテーマ リソース (またはシステム リソース) への参照が実行時に解決されます。
カスタム テーマ リソースのガイドライン
独自のカスタム テーマ リソースを定義して使用するときは、次のガイドラインに従ってください。
"HighContrast" 辞書に加えて、"Light" と "Dark" の両方のテーマ 辞書を指定します。 キーとして "Default" を使用して ResourceDictionary を作成できますが、明示的に指定し、代わりに "Light"、"Dark"、"HighContrast" を使用することをお勧めします。
{ThemeResource} マークアップ拡張は、スタイル、セッター、コントロール テンプレート、プロパティ セッター、アニメーションで使用します。
ThemeDictionaries 内のリソース定義で {ThemeResource} マークアップ拡張機能を使用しないでください。 代わりに {StaticResource} マークアップ拡張 を使用してください。
例外: {ThemeResource} マークアップ拡張機能 を使用して、 ThemeDictionaries のアプリ テーマに依存しないリソースを参照できます。 これらのリソースの例としては、
SystemAccentColor
などのアクセント カラー リソースや、通常はSystemColorButtonFaceColor
のような "SystemColor" というプレフィックスが付いているシステム カラー リソースがあります。
注意事項
これらのガイドラインに従わないと、アプリのテーマに関連する予期しない動作が表示されることがあります。 詳細については、「 テーマ リソースのトラブルシューティング 」セクションを参照してください。
XAML カラー ランプとテーマに依存するブラシ
"Light"、"Dark"、および "HighContrast" テーマの組み合わされた色のセットは、XAML の Windows カラー ランプ を構成します。 システム テーマを変更する場合でも、独自の XAML 要素にテーマを適用する場合でも、カラー リソースの構造を理解することが重要です。
Windows アプリで色を適用する方法の詳細については、「 Windows アプリの色」を参照してください。
明るいテーマと濃色のテーマの色
XAML フレームワークは、"Light" テーマと "Dark" テーマに合わせて調整された値を持つ一連の名前付き Color リソースを提供します。 WinUI 2 の場合、テーマ リソースは 共通テーマ リソース Xaml ファイルで定義されます。 色名は意図した使用法を非常にわかりやすく表しており、すべての Color リソースに対応する SolidColorBrush リソースがあります。
ヒント
これらの色の視覚的な概要については、WinUI 3 ギャラリー アプリの色を参照してください。
WinUI 3 ギャラリー アプリには、ほとんどの WinUI 3 コントロール、機能、および機能の対話型の例が含まれています。 Microsoft Store からアプリを取得するか、GitHub でソース コードを取得する
Windows システムのコントラスト テーマの色
XAML フレームワークによって提供される一連のリソースに加えて、Windows システム パレットから派生した色の値のセットがあります。 これらの色は、Windows ランタイムまたは Windows アプリに固有ではありません。 ただし、多くの XAML ブラシ リソースは、"HighContrast" テーマを使用してシステムが動作している (およびアプリが実行されている) ときに、これらの色を使用します。 XAML フレームワークは、これらのシステム全体の色をキー付きリソースとして提供します。 キーは名前付け形式 ( SystemColor[name]Color
) に従います。
コントラスト テーマのサポートの詳細については、「 コントラスト テーマ」を参照してください。
システムアクセントカラー
システム コントラスト テーマの色に加えて、システムアクセントカラーは、キー SystemAccentColor
を使用した特別な色リソースとして提供されます。 実行時に、このリソースは、Windows パーソナル化設定でユーザーがアクセントカラーとして指定した色を取得します。
注
システム カラー リソースをオーバーライドすることは可能ですが、特にコントラスト テーマの設定では、ユーザーの色の選択を尊重することをお勧めします。
テーマに依存するブラシ
前のセクションで示したカラー リソースは、システム テーマ リソース ディクショナリの SolidColorBrush リソースの Color プロパティを設定するために使用されます。 ブラシ リソースを使用して、XAML 要素に色を適用します。
このブラシの色の値が実行時にどのように決定されるかを見てみましょう。 "Light" および "Dark" リソース ディクショナリでは、このブラシは次のように定義されます。
<SolidColorBrush x:Key="TextFillColorPrimaryBrush" Color="{StaticResource TextFillColorPrimary}"/>
"HighContrast" リソース ディクショナリでは、このブラシは次のように定義されます。
<SolidColorBrush x:Key="TextFillColorPrimaryBrush" Color="{ThemeResource SystemColorWindowTextColor}"/>
このブラシを XAML 要素に適用すると、その色は、次の表に示すように、現在のテーマによって実行時に決定されます。
テーマ | カラー リソース | ランタイム値 |
---|---|---|
淡色 | TextFillColorPrimary | #E4000000 |
暗い | TextFillColorPrimary | #FFFFFFFF |
HighContrast | SystemColorWindowTextColor | Text の設定で指定された色。 |
XAML 型ランプ
themeresources.xaml ファイルには、UI のテキスト コンテナーに適用できる スタイル を定義する複数のリソース (特に TextBlock または RichTextBlock) が定義されています。 これらは既定の暗黙的なスタイルではありません。 これらは、「フォントのガイドライン」に記載されている Windows 型ランプに一致する XAML UI 定義を簡単に作成できるようにするために用意されています。
これらのスタイルは、テキスト コンテナー全体に適用するテキスト属性を対象としています。 テキストのセクションだけにスタイルを適用する場合は、TextBlock.Inlines での実行や RichTextBlock.Blocks の段落など、コンテナー内のテキスト要素に属性を設定します。
TextBlock に適用すると、スタイルは次のようになります。
スタイル | Weight | サイズ |
---|---|---|
キャプション | レギュラー | 12 |
Body | レギュラー | 14 |
ボディストロング | Semibold | 14 |
大きいボディ | レギュラー | 18 |
字幕 | Semibold | 20 |
Title | Semibold | 28 |
大きなタイトル | Semibold | 40 |
Display | Semibold | 68 |
<TextBlock Text="Caption" Style="{StaticResource CaptionTextBlockStyle}"/>
<TextBlock Text="Body" Style="{StaticResource BodyTextBlockStyle}"/>
<TextBlock Text="Body Strong" Style="{StaticResource BodyStrongTextBlockStyle}"/>
<TextBlock Text="Body Large" Style="{StaticResource BodyLargeTextBlockStyle}"/>
<TextBlock Text="Subtitle" Style="{StaticResource SubtitleTextBlockStyle}"/>
<TextBlock Text="Title" Style="{StaticResource TitleTextBlockStyle}"/>
<TextBlock Text="Title Large" Style="{StaticResource TitleLargeTextBlockStyle}"/>
<TextBlock Text="Display" Style="{StaticResource DisplayTextBlockStyle}"/>
アプリで Windows 型ランプを使用する方法のガイダンスについては、「 Windows アプリの文字体裁」を参照してください。
XAML スタイルの詳細については、GitHub の WinUI を参照してください。
ヒント
これらのスタイルのビジュアルの概要については、WinUI 3 ギャラリー アプリの文字体裁に関するページを参照してください。
BaseRichTextBlockStyle
TargetType: RichTextBlock
他のすべての RichTextBlock コンテナー スタイルの共通プロパティを指定します。
<!-- Usage -->
<RichTextBlock Style="{StaticResource BaseRichTextBlockStyle}">
<Paragraph>Rich text.</Paragraph>
</RichTextBlock>
<!-- Style definition -->
<Style x:Key="BaseRichTextBlockStyle" TargetType="RichTextBlock">
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="TextTrimming" Value="None"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="LineStackingStrategy" Value="MaxHeight"/>
<Setter Property="TextLineBounds" Value="Full"/>
<Setter Property="OpticalMarginAlignment" Value="TrimSideBearings"/>
</Style>
BodyRichTextBlockStyle
<!-- Usage -->
<RichTextBlock Style="{StaticResource BodyRichTextBlockStyle}">
<Paragraph>Rich text.</Paragraph>
</RichTextBlock>
<!-- Style definition -->
<Style x:Key="BodyRichTextBlockStyle" TargetType="RichTextBlock" BasedOn="{StaticResource BaseRichTextBlockStyle}">
<Setter Property="FontWeight" Value="Normal"/>
</Style>
注: RichTextBlock スタイルには、主に RichTextBlock のブロックベースのドキュメント オブジェクト モデルを使用すると、個々のテキスト要素に属性を設定することが容易になるため、TextBlock が行うすべてのテキスト ランプ スタイルはありません。 また、XAML コンテンツ プロパティを使用して TextBlock.Text を設定すると、スタイルを設定するテキスト要素がないため、コンテナーのスタイルを設定する必要があります。 これは RichTextBlock の問題ではありません。そのテキスト コンテンツは、ページ ヘッダー、ページ 小見出し、および同様のテキスト ランプ定義に XAML スタイルを適用する場合がある Paragraph などの特定のテキスト要素に常に含まれている必要があるためです。
その他の名前付きスタイル
ボタンのスタイルに適用できるキー付きスタイル定義のセットは、既定の暗黙的なスタイルとは異なります。
NavigationBackButtonNormalStyle
TargetType: ボタン
この スタイル は、ナビゲーション アプリのナビゲーション 戻るボタンとして使用できる ボタン の完全なテンプレートを提供します。 既定の寸法は 40 x 40 ピクセルです。 スタイルを調整するには、Button で Height、Width、FontSize、およびその他のプロパティを明示的に設定するか、BasedOn を使用して派生スタイルを作成します。
NavigationBackButtonNormalStyle リソースが適用された Button を次に示します。
<Button Style="{StaticResource NavigationBackButtonNormalStyle}" />
次のようになります:
NavigationBackButtonSmallStyle
TargetType: ボタン
この スタイル は、ナビゲーション アプリのナビゲーション 戻るボタンとして使用できる ボタン の完全なテンプレートを提供します。 NavigationBackButtonNormalStyle に似ていますが、その寸法は 30 x 30 ピクセルです。
NavigationBackButtonSmallStyle リソースが適用された Button を次に示します。
<Button Style="{StaticResource NavigationBackButtonSmallStyle}" />
テーマ リソースのトラブルシューティング
テーマ リソースを使用するためのガイドラインに従わない場合は、アプリのテーマに関連する予期しない動作が表示されることがあります。
たとえば、明るいテーマのポップアップを開くと、暗いテーマのアプリの一部も、ライト テーマにあるかのように変わります。 または、淡色テーマのページに移動してから戻ると、元の暗いテーマのページ (またはその一部) が淡色テーマにあるかのように見えるようになります。
通常、これらの種類の問題は、ハイ コントラスト シナリオをサポートする "既定" テーマと "HighContrast" テーマを指定した後、アプリのさまざまな部分で "Light" テーマと "Dark" テーマの両方を使用する場合に発生します。
たとえば、次のテーマ ディクショナリの定義を考えてみましょう。
<!-- DO NOT USE. THIS XAML DEMONSTRATES AN ERROR. -->
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Default">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource ControlFillColorDefault}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
直感的に、これは正しく見えます。 ハイ コントラストの場合は myBrush
が指す色を変更する必要がありますが、ハイ コントラストでない場合は、 {ThemeResource} マークアップ拡張機能 に依存して、 myBrush
がテーマの適切な色をポイントしていることを確認します。 アプリのビジュアル ツリー内の要素 に FrameworkElement.RequestedTheme が設定されていない場合、これは通常、期待どおりに動作します。 ただし、ビジュアル ツリーのさまざまな部分のテーマを変更し始めるとすぐに、アプリで問題が発生します。
この問題は、ブラシが他のほとんどの XAML 型とは異なり、共有リソースであるために発生します。 同じブラシ リソースを参照する異なるテーマを持つ XAML サブツリーに 2 つの要素がある場合、フレームワークが各サブツリーをウォークして {ThemeResource} マークアップ拡張 式を更新すると、共有ブラシ リソースへの変更が他のサブツリーに反映されます。これは意図した結果ではありません。
この問題を解決するには、"HighContrast" に加えて、"Light" テーマと "Dark" テーマの両方の個別のテーマ ディクショナリに "Default" ディクショナリを置き換えます。
<!-- DO NOT USE. THIS XAML DEMONSTRATES AN ERROR. -->
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource ControlFillColorDefault}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource ControlFillColorDefault}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
ただし、これらのリソースのいずれかが Foreground などの継承されたプロパティで参照されている場合は、問題が引き続き発生します。 カスタム コントロール テンプレートでは 、{ThemeResource} マークアップ拡張を使用して要素の前景色を指定できますが、フレームワークが継承された値を子要素に反映すると、{ThemeResource} マークアップ拡張式によって解決されたリソースへの直接参照が提供されます。 これにより、フレームワークがコントロールのビジュアル ツリーを表示するときにテーマの変更を処理するときに問題が発生します。 {ThemeResource} マークアップ拡張式を再評価して新しいブラシ リソースを取得しますが、この参照をコントロールの子にまだ反映していません。これは、次のメジャー パス中など、後で発生します。
その結果、テーマの変更に応じてコントロールビジュアル ツリーをウォークした後、フレームワークは子をウォークし、それらに設定された {ThemeResource} マークアップ拡張 式、またはプロパティに設定されたオブジェクトを更新します。 ここで問題が発生します。フレームワークはブラシ リソースをウォークし、{ThemeResource} マークアップ拡張を使用してその色を指定するため、再評価されます。
この時点で、フレームワークはテーマディクショナリを汚染しているように見えます。これは、ある辞書のリソースがあり、その色が別の辞書から設定されているためです。
この問題を解決するには、 {ThemeResource} マークアップ拡張 の代わりに {StaticResource} マークアップ拡張機能を使用します。 ガイドラインを適用すると、テーマ ディクショナリは次のようになります。
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="myBrush" Color="{StaticResource ControlFillColorDefault}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="myBrush" Color="{StaticResource ControlFillColorDefault}"/>
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush x:Key="myBrush" Color="{ThemeResource SystemColorButtonFaceColor}"/>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
{ThemeResource} マークアップ拡張は、{StaticResource} マークアップ拡張ではなく "HighContrast" ディクショナリで引き続き使用されていることに注意してください。 この状況は、ガイドラインで前述した例外に該当します。 "HighContrast" テーマに使用されるブラシ値のほとんどは、システムによってグローバルに制御されるが、特別な名前のリソース (名前に "SystemColor" がプレフィックス付き) として XAML に公開されている色の選択を使用しています。 システムを使用すると、ユーザーは簡単操作センターを使用して、コントラスト テーマの設定に使用する必要がある特定の色を設定できます。 これらの色の選択は、特別な名前のリソースに適用されます。 XAML フレームワークでは、同じテーマ変更イベントを使用して、システム レベルで変更されたことを検出したときにこれらのブラシも更新します。 これが、{ThemeResource} マークアップ拡張機能がここで使用される理由です。
Windows developer