共用方式為


XAML 樣式

您可以使用 XAML 架構,以多種方式自訂應用程式的外觀。 樣式可讓您設定控件屬性,並重複使用這些設定,以便在多個控件之間一致的外觀。

WinUI 和樣式

從 WinUI 2.2 開始,我們已使用 WinUI 跨 UI 元件提供新的視覺樣式更新。 如果您注意到UI未更新為最新的樣式,請務必更新為最新的WinUI NuGet 套件。

從 WinUI 2.6 開始,我們為大部分的控件提供新的樣式,以及新的版本設定系統,可讓您視需要還原為先前的控件樣式。 我們鼓勵您使用新的樣式,因為它們更符合 Windows 的設計方向。 不過,如果您的案例無法支援新的樣式,則舊版仍可供使用。

您可以在使用 WinUI 第 2 版時,透過在包含於 ControlsResourcesVersionXamlControlsResources 上設定 Application.Resources 屬性來變更樣式版本。 ControlsResourcesVersion 預設為列舉值 Version2

將此值設定為 Version1 會導致 XamlControlsResources 載入先前的樣式版本,而不是最新 WinUI 版本所使用的新樣式。 不支援在運行時間變更此屬性,而且VisualStudio的熱重載功能將無法運作;不過,在重建應用程式之後,您會看到控件樣式變更。

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

樣式基礎知識

使用樣式將可視化屬性設定擷取至可重複使用的資源。 以下是顯示 3 個按鈕的範例,其中包含設定 BorderBrushBorderThicknessForeground 屬性的樣式。 藉由套用樣式,您可以讓控件看起來相同,而不需要分別在每個控件上設定這些屬性。

三個並排樣式按鈕的螢幕截圖。

您可以在控件的 XAML 中內嵌定義樣式,或將其定義為可重複使用的資源。 在個別頁面的 XAML 檔案、App.xaml 檔案或個別資源字典 XAML 檔案中定義資源。 資源字典 XAML 檔案可以跨應用程式共用,而且可以在單一應用程式中合併多個資源字典。 定義資源的位置會決定其可使用的範圍。 頁面層級資源只能在定義它們的頁面中使用。 如果在 App.xaml 和頁面中定義具有相同索引鍵的資源,則頁面中的資源會覆寫 App.xaml 中的資源。 如果資源是在個別的資源字典檔案中定義,則其範圍取決於參考資源字典的位置。

Style 的定義中,您需要一個 TargetType 屬性,以及一組包含一或多個 Setter 元素的集合。 TargetType 屬性是一個字串,指定一個 FrameworkElement 類型來套用樣式。 TargetType 值必須指定 Windows 運行時間所定義的 FrameworkElement衍生類型,或參考元件中可用的自定義類型。 如果您嘗試將樣式套用至控件,且控件的類型不符合您嘗試套用之樣式的 TargetType 屬性,就會發生例外狀況。

每個 Setter 元素都需要一個 屬性 和一個 。 這些屬性設定會指出設定所套用的控件屬性,以及要為該屬性設定的值。 您可以使用屬性或屬性元素語法來設定 Setter.Value。 這裡的 XAML 顯示了先前所展示按鈕的樣式。 在此 XAML 中,前兩個 Setter 元素使用屬性語法,但 BorderBrush 屬性的最後一個 Setter 會使用屬性元素語法。 此範例不會使用 x:Key 屬性 屬性,因此樣式會隱含地套用至按鈕。 下一節將說明如何隱含或顯式地套用樣式。

<Page.Resources>
    <Style TargetType="Button">
        <Setter Property="BorderThickness" Value="5" />
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="BorderBrush" >
            <Setter.Value>
                <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                    <GradientStop Color="Yellow" Offset="0.0" />
                    <GradientStop Color="Red" Offset="0.25" />
                    <GradientStop Color="Blue" Offset="0.75" />
                    <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
    </Style>
</Page.Resources>

<StackPanel Orientation="Horizontal">
    <Button Content="Button"/>
    <Button Content="Button"/>
    <Button Content="Button"/>
</StackPanel>

套用隱含或明確樣式

如果您將樣式定義為資源,有兩種方式可將它套用至控制項:

如果樣式包含 x:Key 屬性,則您只能透過將控件的 Style 屬性設定為具索引鍵的樣式,來將它套用至控件。 相反地,沒有 x:Key 屬性的樣式會自動套用至其目標類型的每個控件,否則不會有明確的樣式設定。

以下是示範隱含和明確樣式的兩個按鈕。

隱含和明確設定樣式的按鈕。

在這個範例中,第一個樣式具有 x:Key 屬性,且其目標類型是 Button。 第一個按鈕的 Style 屬性會設定為此鍵值,因此會明確套用此樣式。 第二個樣式會隱含地套用至第二個按鈕,因為其目標類型為 Button ,而且樣式沒有 x:Key 屬性。

<Page.Resources>
    <Style x:Key="PurpleStyle" TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="Foreground" Value="Purple"/>
    </Style>

    <Style TargetType="Button">
        <Setter Property="FontFamily" Value="Segoe UI"/>
        <Setter Property="FontSize" Value="14"/>
        <Setter Property="RenderTransform">
            <Setter.Value>
                <RotateTransform Angle="25"/>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderBrush" Value="Green"/>
        <Setter Property="BorderThickness" Value="2"/>
        <Setter Property="Foreground" Value="Green"/>
    </Style>
</Page.Resources>

<Grid x:Name="LayoutRoot">
    <Button Content="Button" Style="{StaticResource PurpleStyle}"/>
    <Button Content="Button"/>
</Grid>

使用以為基礎的樣式

為了讓樣式更容易維護,以及優化樣式的再利用,您可以建立從其他樣式繼承的樣式。 您可以使用 BasedOn 屬性來建立繼承的樣式。 繼承自其他樣式的樣式必須以相同類型的控件或衍生自基底樣式目標類型的控件為目標。 例如,如果基底樣式以 ContentControl為目標,則以此樣式為基礎的樣式可以針對 ContentControl 或針對衍生自 ContentControl 的類型,例如 ButtonScrollViewer。 如果在依據樣式中未設定值,則會從基礎樣式繼承該值。 若要變更基底樣式的值,繼承自該基底樣式的樣式會覆寫該值。 下一個範例顯示一個 Button 和一個 CheckBox,這兩者的樣式都繼承自相同的基底樣式。

使用基於樣式的設計樣式的按鈕。

基底樣式會以 ContentControl 為目標,並設定 HeightWidth 屬性。 以此樣式目標為基礎的樣式 CheckBoxButton,其衍生自 ContentControl。 根據的樣式為 BorderBrushForeground 屬性設定了不同的顏色。 (您通常不會在核取方塊 周圍放置框線。我們在這裡這樣做,以顯示樣式的效果。)

<Page.Resources>
    <Style x:Key="BasicStyle" TargetType="ContentControl">
        <Setter Property="Width" Value="130" />
        <Setter Property="Height" Value="30" />
    </Style>

    <Style x:Key="ButtonStyle" TargetType="Button"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Orange" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Red" />
    </Style>

    <Style x:Key="CheckBoxStyle" TargetType="CheckBox"
           BasedOn="{StaticResource BasicStyle}">
        <Setter Property="BorderBrush" Value="Blue" />
        <Setter Property="BorderThickness" Value="2" />
        <Setter Property="Foreground" Value="Green" />
    </Style>
</Page.Resources>

<StackPanel>
    <Button Content="Button" Style="{StaticResource ButtonStyle}" Margin="0,10"/>
    <CheckBox Content="CheckBox" Style="{StaticResource CheckBoxStyle}"/>
</StackPanel>

使用工具輕鬆地處理樣式

將樣式快速套用至控件的方法是以滑鼠右鍵按一下 Microsoft Visual Studio XAML 設計介面上的控件,然後選取 [編輯樣式][編輯範本](取決於您右鍵點選的控件)。 然後,您可以透過選取 [套用資源] 來套用現有的樣式,或選取 [建立空白]來定義新的樣式。 如果您建立空的樣式,您可以選擇在頁面、App.xaml 檔案或個別的資源字典中定義它。

輕量化造型

覆寫系統畫筆一般是在應用程式或頁面層級進行,無論在哪種情況下,色彩覆寫都會影響所有參考該畫筆的控制項,而在 XAML 中,許多控制項可以參考相同的系統畫筆。

兩個按鈕的螢幕截圖: 一個處於靜止狀態,另一個已套用輕量化樣式。

<Page.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Light">
                 <SolidColorBrush x:Key="ButtonBackground" Color="Transparent"/>
                 <SolidColorBrush x:Key="ButtonForeground" Color="MediumSlateBlue"/>
                 <SolidColorBrush x:Key="ButtonBorderBrush" Color="MediumSlateBlue"/>
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Page.Resources>

針對 PointerOver 等狀態(滑鼠停留在按鈕上)、PointerPressed(已叫用按鈕),或 [停用] (按鈕無法互動)。 這些結尾會附加至原始輕量樣式名稱:ButtonBackgroundPointerOverButtonForegroundPressedButtonBorderBrushDisabled等。相應地修改這些筆刷可確保您的控制項顏色與應用程式的主題一致。

如果將這些筆刷覆寫放置在 App.Resources 層級,將會改變整個應用程式內的所有按鈕,而不是僅在單一頁面上進行更改。

個別控件樣式

在某些情況下,希望僅在單一頁面上更改一個控件的外觀,而不影響該控件的其他版本:

三個樣式按鈕的螢幕快照,其中一個排列在另一個上方。

<CheckBox Content="Normal CheckBox" Margin="5"/>
<CheckBox Content="Special CheckBox" Margin="5">
    <CheckBox.Resources>
        <ResourceDictionary>
            <ResourceDictionary.ThemeDictionaries>
                <ResourceDictionary x:Key="Light">
                    <SolidColorBrush x:Key="CheckBoxForegroundUnchecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxForegroundChecked"
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckGlyphForegroundChecked"
                        Color="White"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundStrokeChecked"  
                        Color="Purple"/>
                    <SolidColorBrush x:Key="CheckBoxCheckBackgroundFillChecked"
                        Color="Purple"/>
                </ResourceDictionary>
            </ResourceDictionary.ThemeDictionaries>
        </ResourceDictionary>
    </CheckBox.Resources>
</CheckBox>
<CheckBox Content="Normal CheckBox" Margin="5"/>

這隻會影響該控件存在之頁面上的一個「特殊 CheckBox」。

自訂控制項

當您建立自己的自訂控制項時,這些控制項可能在視覺上和/或功能上與內建控制項一致,請考慮使用隱含樣式和精簡樣式資源來定義您的自訂內容。 您可以直接使用資源,或為資源建立新的別名。

直接使用控制資源

例如,如果您要撰寫看起來像 Button 的控件,您可以讓控件直接參考按鈕資源,如下所示:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
</Style>

將控件資源別名化為新名稱

或者,如果您想要建立自己的資源,您應該將這些自定義名稱別名為我們預設的輕量型樣式資源。

例如,自定義控件的樣式可能有特殊的資源定義:

<Style TargetType="local:MyCustomControl">
  <Setter Property="Background" Value="{ThemeResource MyCustomControlBackground}" />
  <Setter Property="BorderBrush" Value="{ThemeResource MyCustomControlBorderBrush}"/>
</Style>

在您的資源字典或主要定義中,您會將輕量型樣式資源連結至自定義資源:

<ResourceDictionary.ThemeDictionaries>
    <ResourceDictionary x:Key="Default">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>        
    <ResourceDictionary x:Key="Light">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
    <ResourceDictionary x:Key="HighContrast">
        <StaticResource x:Key="MyCustomControlBackground" ResourceKey="ButtonBackground" />
        <StaticResource x:Key="MyCustomControlBorderBrush" ResourceKey="ButtonBorderBrush" />
    </ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>

您必須使用要重複三次的ThemeDictionary,以便正確處理三個不同的主題變更(DefaultLightHighContrast)。

謹慎

如果您將輕量型樣式資源指派給新的別名,並且重新定義輕量型樣式資源,則如果資源查閱順序不正確,您的自定義可能不會被套用。 例如,如果您在找到 ButtonBackground 之前搜尋的位置覆寫 MyCustomControlBackground,則會遺漏覆寫。

避免重新樣式化控件

WinUI 2.2 或更新版本包含 WinUI 和系統控制項的新樣式和範本。

保持最新可視化樣式的最佳方式是使用最新的 WinUI 2 套件,並避免自定義樣式和範本(也稱為重新範本化)。 樣式仍然是一種方便的方式,可在應用程式中的控件之間一致地套用一組值。 這樣做時,請務必確保以我們最新的樣式為基礎。

對於使用 WinUI 樣式的系統控制件 (Windows.UI.Xaml.Controls 命名空間),請設定 BasedOn="{StaticResource Default<ControlName>Style}",其中 <ControlName> 是控件的名稱。 例如:

<Style TargetType="TextBox" BasedOn="{StaticResource DefaultTextBoxStyle}">
    <Setter Property="Foreground" Value="Blue"/>
</Style>

針對 WinUI 2 控制件 (Microsoft.UI.Xaml.Controls 命名空間),預設樣式會在元資料中定義,因此請省略 BasedOn

衍生控件

如果您從現有的 XAML 控件衍生自定義控件,則預設不會取得 WinUI 2 樣式。 若要套用 WinUI 2 樣式:

  • 建立新的 Style,並將其 TargetType 設為您的自定義控制項。
  • 以您衍生自之控件的預設樣式為基礎。

其中一個常見案例是從 ContentDialog 衍生新控件。 此範例示範如何建立套用 DefaultContentDialogStyle 至自定義對話框的新 Style。

<ContentDialog
    x:Class="ExampleApp.SignInContentDialog"
    ... >

    <ContentDialog.Resources>
        <Style TargetType="local:SignInContentDialog" BasedOn="{StaticResource DefaultContentDialogStyle}"/>
        ...
    </ContentDialog.Resources> 
    <!-- CONTENT -->
</ContentDialog>        

範本屬性

樣式 setter 可用於 控件Template 屬性,事實上,這構成大部分的典型 XAML 樣式和應用程式的 XAML 資源。 本主題將在 控制範本中更詳細地討論。