共用方式為


XAML 佈景主題資源

XAML中的主題資源是一組資源,根據啟用的系統主題,套用不同的值。 XAML 架構支援 3 個主題:[淺色]、[深色] 和 [HighContrast]。

必要條件:本主題假設您已閱讀 ResourceDictionary 和 XAML 資源參考

主題資源與靜態資源

有兩個 XAML 標記延伸可以從現有的 XAML 資源字典參考 XAML 資源:{StaticResource} 標記延伸{ThemeResource} 標記延伸

當應用程式載入,並在執行階段每次變更主題時,就會發生 {ThemeResource} 標記延伸的評估。 這通常是使用者變更其裝置設定的結果,或是從改變其目前主題的應用程式內以程式設計方式變更的結果。

相反地,只有在應用程式第一次載入 XAML 時,才會評估 {StaticResource} 標記延伸。 這不會更新。 它類似於在 XAML 中尋找並替換為應用程式啟動時的實際執行階段值。

資源字典結構中的佈景主題資源

每個主題資源都是 XAML 檔案 themeresources.xaml 的一部分。 基於設計目的,Windows 軟體開發套件 (SDK) 安裝的 \(Program Files)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\<SDK version>\Generic 資料夾中會提供 themeresources.xaml。 themeresources.xaml 中的資源字典也會在同目錄中的 generic.xaml 中重現。

Windows 執行階段不會使用這些實體檔案進行執行階段查詢。 這就是為什麼它們特別位於 [DesignTime] 資料夾中,而且預設不會複製到應用程式。 相反地,這些資源字典會存在於記憶體中,做為「Windows 執行階段」本身的一部分,而應用程式對主題資源 (或系統資源) 的 XAML 資源參考會在執行階段解析到該處。

自訂佈景主題資源的指導方針

當您定義並取用自己的自訂佈景主題資源時,請遵循下列指導方針:

警告

如果未遵循這些指導方針,您可能會在您的應用程式中看到與主題相關的非預期行為。 如需更多資訊,請參閱疑難排解主題資源一節。

XAML 色彩坡形和主題相依筆刷

[淺色]、[深色] 和 [HighContrast] 主題的一組組合色彩,組成 XAML 中的 Windows 色彩坡形。 無論您是要修改系統主題,還是將主題套用至自己的 XAML 元素,都必須了解色彩資源的結構化方式。

如需有關如何在 Windows 應用程式中套用色彩的詳細資訊,請參閱 Windows 應用程式中的色彩

淺色和深色主題色彩

XAML 架構提供一組名為 [色彩] 的資源,其中包含針對 [淺色] 和 [深色] 主題量身打造的值。 針對 WinUI 2,主題資源定義於通用主題資源 Xaml 檔案。 色彩名稱清晰描述其預定的使用方式,而且每個 [色彩] 資源都有對應的 SolidColorBrush 資源。

提示

如需這些色彩的視覺概觀,請參閱 WinUI 3 資源庫應用程式:色彩

WinUI 3 資源庫應用程式包含大多數 WinUI 3 控制項和功能的互動式範例。 從 Microsoft Store 取得應用程式,或在 GitHub 上取得原始程式碼

Windows 系統對比主題色彩

除了 XAML 架構所提供的一組資源之外,還有一組衍生自 Windows 系統調色盤的色彩值。 這些色彩並不是 Windows 執行階段或 Windows 應用程式專用的。 不過,當系統運作時,許多 XAML 筆刷資源會使用 [HighContrast] 主題來取用這些色彩。 XAML 架構會提供這些全系統色彩作為索引鍵資源。 索引鍵會遵循命名格式:SystemColor[name]Color

如需支援對比主題的詳細資訊,請參閱對比主題

系統輔色

除了系統對比主題色彩之外,系統輔色也會使用索引鍵 SystemAccentColor 作為特殊色彩資源提供。 在執行階段,此資源會取得使用者在 Windows 個人化設定中指定為輔色的色彩。

注意

雖然可以覆寫系統色彩資源,但是最佳作法還是尊重使用者的色彩選擇,特別是針對對比主題設定。

佈景主題相依筆刷

前述各節中顯示的色彩資源可用來設定系統佈景主題資源字典中 SolidColorBrush 資源的 [色彩] 屬性。 您可以使用筆刷資源,將色彩套用到 XAML 元素。

讓我們看看此筆刷的色彩值在執行階段如何決定。 在 [淺色] 和 [深色] 資源字典中,此筆刷的定義如下:

<SolidColorBrush x:Key="TextFillColorPrimaryBrush" Color="{StaticResource TextFillColorPrimary}"/>

在 [HighContrast] 資源字典中,此筆刷的定義如下:

<SolidColorBrush x:Key="TextFillColorPrimaryBrush" Color="{ThemeResource SystemColorWindowTextColor}"/>

當此筆刷套用至 XAML 元素時,其色彩會在執行階段由目前的主題決定,如此資料表所示。

佈景主題 色彩資源 執行階段值
淺色 TextFillColorPrimary #E4000000
深色 TextFillColorPrimary #FFFFFFFF
HighContrast SystemColorWindowTextColor [文字] 設定中指定的色彩。

XAML 類型坡形

themeresources.xaml 檔案會定義數個資源,這些資源定義您可以套用至 UI 中的文字容器的 [樣式],特別是針對 [TextBlock][RichTextBlock]。 這些不是預設的隱含樣式。 它們提供的是為了讓您更容易地在符合字體指南中所記錄的 Windows 字體坡型的 XAML UI 定義。

這些樣式是用於您想要套用到整個文字容器的文字屬性。 如果只想將樣式套用到文字的區段,請針對容器內的文字元素設定屬性,例如,TextBlock.Inlines 中的 [執行]RichTextBlock.Blocks 中的 [段落]

當套用至 TextBlock 時樣式看起來像這樣:

text block styles

樣式 Weight 大小
標題 一般 12
本文 一般 14
本文強式 半粗體 14
本文大尺寸 一般 18
子標題 半粗體 20
標題 半粗體 28
標題大尺寸 半粗體 40
顯示器 半粗體 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 樣式並沒有 TextBlock 擁有的所有文字坡形樣式,主要是因為 RichTextBlock 的區塊型文件物件模型,讓您能夠更容易針對個別的文字元素設定屬性。 此外,使用 XAML 內容屬性設定 TextBlock.Text,也會導致沒有要文字元素可供樣式化,因此您必須對容器進行樣式化。 這對 RichTextBlock 來說並不是問題,因為它的文字內容一律必須位於特定的文字元素 (例如 Paragraph) 中,這是您可能為頁首、子頁首及類似文字坡形定義套用 XAML 樣式的地方。

其他具名樣式

有一組額外的索引鍵 [樣式] 定義,您可以套用至設定[按鈕] 的樣式,與其預設的隱含樣式不同。

TargetType[按鈕]

這個 [樣式] 提供了一個完整的 [按鈕] 範本,可以作為瀏覽應用程式的返回按鈕。 預設尺寸為 40 x 40 像素。 若要量身打造樣式,您可以在 [按鈕] 上明確設定 [高度][寬度][FontSize] 及其他屬性,或者使用 [BasedOn] 建立衍生的樣式。

以下是已套用 NavigationBackButtonNormalStyle 資源的 [按鈕]

<Button Style="{StaticResource NavigationBackButtonNormalStyle}" />

畫面顯示為這樣:

A button styled as a back button

TargetType[按鈕]

這個 [樣式] 提供了一個完整的 [按鈕] 範本,可以作為瀏覽應用程式的返回按鈕。 與 NavigationBackButtonNormalStyle 類似,但尺寸是 30 x 30 像素。

以下是已套用 NavigationBackButtonSmallStyle 資源的 [按鈕]

<Button Style="{StaticResource NavigationBackButtonSmallStyle}" />

疑難排解主題資源

如果未遵循使用主題資源的指導方針,您可能會在您的應用程式中看到與主題相關的非預期行為。

例如,當您開啟淺色主題飛出視窗時,深色主題應用程式的部分也會變更,就像它們位於淺色主題中一樣。 或者,如果您瀏覽至淺色主題頁面,然後往回瀏覽,原始深色主題頁面 (或部分頁面) 現在看起來就像是在淺色主題中。

通常,當您提供 [預設] 主題和 [高對比度] 主題以支援高對比度案例時,並在應用程式的不同部分使用 [淺色] 和 [深色] 主題時,就會出現這類問題。

例如,請考慮此主題字典定義:

<!-- 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] 之外,請將 [預設] 字典取代為 [淺色] 和 [深色] 主題的個別主題字典:

<!-- 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} 標記延伸仍會在 [HighContrast] 字典中使用,而不是 {StaticResource} 標記延伸。 這種情況屬於指導方針稍早指定的例外狀況。 大部分用於 [HighContrast] 主題的筆刷值,都是使用由系統全域控制的色彩選擇,但公開給 XAML 作為特別命名的資源 (名稱前面中加上 'SystemColor')。 系統可讓使用者透過 [輕鬆存取中心] 來設定應該用於其對比主題設定的特定色彩。 這些色彩選項會套用至特別命名的資源。 XAML 架構會使用相同的主題變更事件,在偵測到系統層級變更時,也會更新這些筆刷。 這就是為什麼在這裡使用 {ThemeResource} 標記延伸的原因。