控件範本

您可以在 XAML 架構中建立控制項範本,以自訂控件的視覺結構和視覺行為。 控件有許多屬性,例如 Background、 Foreground 和 FontFamily,您可以設定為指定控件外觀的不同層面。 但是您可以藉由設定這些屬性所做的變更受到限制。 您可以使用 ControlTemplate 類別來建立範本,以指定其他自訂項目。 在這裡,我們會示範如何建立 ControlTemplate 來自定義 CheckBox 控件的外觀。

重要 API: ControlTemplate 類別Control.Template 屬性

自定義控件範例

根據預設,CheckBox 控件會將其內容(CheckBox旁的字串或物件)放在勾選方塊的右邊,而勾選標記顯示用戶已選擇了 CheckBox。 這些特性代表 CheckBox 的視覺結構和視覺行為。

以下是使用預設 ControlTemplate 顯示在 、和 Unchecked 狀態中的 Checked。

默認複選框範本

您可以建立 ControlTemplate 來變更 CheckBox的這些特性。 例如,如果您想要複選框的內容在選取方塊下方,而您想要使用 X 來指出使用者選取複選框。 您可以在 ControlTemplate 的 CheckBox中指定這些特性。

若要搭配控制項使用自定義範本,請將 ControlTemplate 指派給控制項的 Template 屬性。 以下是使用稱為 ControlTemplate 的 CheckBox。 我們將在下一節中顯示 ControlTemplate 的可延伸應用程式標記語言 (XAML)。

<CheckBox Content="CheckBox" Template="{StaticResource CheckBoxTemplate1}" IsThreeState="True" Margin="20"/>

以下是此 CheckBox 在套用範本之後的外觀,對應於 Unchecked、Checked和 Indeterminate 狀態。

自定義複選框範本

指定一個控件的視覺結構

當您建立 ControlTemplate 時,您可以結合 FrameworkElement 物件來建置單一控件。 ControlTemplate 必須只有一個 FrameworkElement 做為其根元素。 根元素通常包含其他 FrameworkElement 物件。 對象的組合構成控件的視覺結構。

此 XAML 會建立 CheckBox 的 ControlTemplate,指定控件的內容位於選取方塊下方。 根元素是 Border。 此範例會指定 Path 來建立一個 X,這表示使用者選取了 CheckBox,並建立一個 Ellipse,顯示不確定的狀態。 注意,Opacity 在 Path 和 Ellipse 上預設設定為 0,因此兩者預設情況下不會顯示。

TemplateBinding 是一種特殊的系結,可將控件範本中屬性的值連結到樣板化控件上其他公開屬性的值。 TemplateBinding 只能在 XAML 中的 ControlTemplate 定義中使用。 如需詳細資訊,請參閱 TemplateBinding 標記延伸。

備註

從 Windows 10 版本 1809(SDK 17763)開始,你可以在使用 TemplateBinding 的地方使用 x:Bind 標記擴充功能。 如需詳細資訊,請參閱 TemplateBinding 標記延伸。

<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">
    <Border BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>
            <Rectangle x:Name="NormalRectangle" Fill="Transparent" Height="20" Width="20"
                       Stroke="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
                       StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"
                       UseLayoutRounding="False"/>
            <!-- Create an X to indicate that the CheckBox is selected. -->
            <Path x:Name="CheckGlyph"
                  Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z"
                  Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                  FlowDirection="LeftToRight"
                  Height="14" Width="16" Opacity="0" Stretch="Fill"/>
            <Ellipse x:Name="IndeterminateGlyph"
                     Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                     Height="8" Width="8" Opacity="0" UseLayoutRounding="False" />
            <ContentPresenter x:Name="ContentPresenter"
                              ContentTemplate="{TemplateBinding ContentTemplate}"
                              Content="{TemplateBinding Content}"
                              Margin="{TemplateBinding Padding}" Grid.Row="1"
                              HorizontalAlignment="Center"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </Border>
</ControlTemplate>

指定控件的視覺行為

視覺行為會指定控件處於特定狀態時的外觀。 CheckBox 控制件有 3 個檢查狀態:Checked、 Unchecked和 Indeterminate。 IsChecked 屬性的值會決定 核取方塊的狀態,而其狀態會決定方塊中出現的內容。

下表列出 IsChecked的可能值、 CheckBox 的對應狀態,以及 CheckBox 的外觀。

IsChecked 值 CheckBox 狀態 CheckBox 外觀
是 Checked 包含 「X」。。
假 Unchecked 空白。
零 Indeterminate 包含圓形。

當您使用 VisualState 物件處於特定狀態時,您可以指定控件的外觀。 VisualState 包含 Setter 或 Storyboard,變更 ControlTemplate中項目的外觀。 當控件進入 VisualState.Name 屬性指定的狀態時,會套用 Setter 或 Storyboard 中的屬性變更。 當控件結束狀態時,會移除變更。 您可以將 VisualState 物件新增至 VisualStateGroup 物件。 您會將 VisualStateGroup 物件新增至 VisualStateManager.VisualStateGroups 附加屬性,這是您在 ControlTemplate 的根 FrameworkElement 上設定的。

此 XAML 會顯示 、和 Checked 狀態 Unchecked 物件。 此範例會設定 Border上 VisualStateManager.VisualStateGroups 附加屬性,這是 ControlTemplate的根元素。 VisualState 指定名為 的 Path 的 Opacity (如上一個範例所示)為 1。 Indeterminate VisualState 指定名為 的 Ellipse 之 IndeterminateGlyph 為 1。 Unchecked VisualState 沒有 Setter 或 Storyboard,因此 CheckBox 會回到其默認外觀。

<ControlTemplate x:Key="CheckBoxTemplate1" TargetType="CheckBox">
    <Border BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}"
            Background="{TemplateBinding Background}">

        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="CheckStates">
                <VisualState x:Name="Checked">
                    <VisualState.Setters>
                        <Setter Target="CheckGlyph.Opacity" Value="1"/>
                    </VisualState.Setters>
                    <!-- This Storyboard is equivalent to the Setter. -->
                    <!--<Storyboard>
                        <DoubleAnimation Duration="0" To="1"
                         Storyboard.TargetName="CheckGlyph" Storyboard.TargetProperty="Opacity"/>
                    </Storyboard>-->
                </VisualState>
                <VisualState x:Name="Unchecked"/>
                <VisualState x:Name="Indeterminate">
                    <VisualState.Setters>
                        <Setter Target="IndeterminateGlyph.Opacity" Value="1"/>
                    </VisualState.Setters>
                    <!-- This Storyboard is equivalent to the Setter. -->
                    <!--<Storyboard>
                        <DoubleAnimation Duration="0" To="1"
                         Storyboard.TargetName="IndeterminateGlyph" Storyboard.TargetProperty="Opacity"/>
                    </Storyboard>-->
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="*"/>
                <RowDefinition Height="25"/>
            </Grid.RowDefinitions>
            <Rectangle x:Name="NormalRectangle" Fill="Transparent" Height="20" Width="20"
                       Stroke="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
                       StrokeThickness="{ThemeResource CheckBoxBorderThemeThickness}"
                       UseLayoutRounding="False"/>
            <!-- Create an X to indicate that the CheckBox is selected. -->
            <Path x:Name="CheckGlyph"
                  Data="M103,240 L111,240 119,248 127,240 135,240 123,252 135,264 127,264 119,257 111,264 103,264 114,252 z"
                  Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                  FlowDirection="LeftToRight"
                  Height="14" Width="16" Opacity="0" Stretch="Fill"/>
            <Ellipse x:Name="IndeterminateGlyph"
                     Fill="{ThemeResource CheckBoxForegroundThemeBrush}"
                     Height="8" Width="8" Opacity="0" UseLayoutRounding="False" />
            <ContentPresenter x:Name="ContentPresenter"
                              ContentTemplate="{TemplateBinding ContentTemplate}"
                              Content="{TemplateBinding Content}"
                              Margin="{TemplateBinding Padding}" Grid.Row="1"
                              HorizontalAlignment="Center"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Grid>
    </Border>
</ControlTemplate>

若要進一步瞭解 VisualState 對象的運作方式,請考慮 CheckBox 從 Unchecked 狀態到 Checked 狀態、 Indeterminate 狀態,然後回到 Unchecked 狀態時會發生什麼情況。 以下是過渡。

狀態轉換 會發生什麼事 轉換完成時的 CheckBox 外觀
從 Unchecked 到 Checked。 Setter 的值會被應用於 CheckedVisualState,因此 的 為 1。 一個 X 被顯示出來。
從 Checked 到 Indeterminate。 Setter 的值會被應用於 IndeterminateVisualState,因此 的 為 1。 會移除 VisualState 的 CheckedSetter 值,因此的不透明度CheckGlyph為 0。 隨即顯示圓形。
從 Indeterminate 到 Unchecked。 Setter 值已移除,因此 IndeterminateVisualState 的 的 為 0。 不會顯示任何內容。

 如需如何建立控件視覺狀態的詳細資訊,特別是如何使用 Storyboard 類別和動畫類型,請參閱 視覺狀態的分鏡腳本動畫。

使用工具輕鬆管理主題設定

快速套用主題的方法是右鍵點擊Microsoft Visual Studio 文件大綱中的控制項,選擇編輯主題或編輯風格(視你右鍵點擊的控制項而定)。 然後,您可以選取 [ 套用資源 ] 來套用現有的主題,或選取 [ 建立空白] 來定義新的主題。

控制選項和輔助功能

當您為控件建立新的範本時,除了可能變更控件的行為和視覺外觀之外,您可能也會變更控件將本身呈現為輔助功能架構的方式。 Windows app 支援 Microsoft 使用者介面自動化 框架以提升無障礙性。 所有預設控制項及其範本都支援適用於控制項用途與功能的常見 使用者介面自動化 控制類型與模式。 這些控制類型與模式會被 使用者介面自動化 客戶端(如輔助技術)解讀,使控制項能作為更大且可存取的應用程式 UI 的一部分。

為了分離基本控制邏輯並滿足 使用者介面自動化 的一些架構需求,控制類別將其無障礙支援納入一個獨立的類別,即自動化對等單元。 自動化對應有時會與控制範本互動,因為對應預期範本中會存在某些具名元件,以便啟用輔助技術來觸發按鈕動作等功能。

當您建立全新的自定義控制項時,您有時也會想要建立新的自動化同級控制項與其搭配。 如需詳細資訊,請參閱 自訂自動化合作對象。

深入瞭解控件的預設範本

描述 XAML 控制項樣式和範本的章節會顯示出在先前提到使用的 編輯主題 或 編輯樣式 技巧時可見的相同起始 XAML 的摘錄。 每個主題都會列出視覺狀態的名稱、所使用的主題資源,以及包含範本之樣式的完整 XAML。 如果您已經開始修改範本,並想要查看原始範本的外觀或確認您的新範本是否具備所有必需的具名視覺狀態,這些主題可能會是有用的指南。

控件範本中的主題資源

對於 XAML 範例中的某些屬性,您可能已經注意到使用 {ThemeResource} 標記延伸的資源參考。 這是一種技術,可讓單一控件範本使用資源,視目前作用中的主題而定,這些資源可以是不同的值。 對於筆刷和色彩來說,這特別重要,因為主題的主要目的是讓用戶選擇要套用至整體系統的深色、淺色或高對比度主題。 使用 XAML 資源系統的應用程式可以使用適用於該主題的資源集,讓應用程式 UI 中的主題選擇反映使用者的全系統主題選擇。

取得範例程式碼