控制項範本

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

重要的 APIControlTemplate 類別Control.Template 屬性

自訂控制項範例

根據預設,CheckBox 控制項會將其內容 (CheckBox 旁的字串或物件) 放在選取方塊右邊,而核取記號表示使用者已選取 CheckBox。 這些特性代表 CheckBox 的視覺結構和視覺行為。

以下是使用 UncheckedCheckedIndeterminate 狀態中顯示的預設 ControlTemplateCheckBox

default checkbox template

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

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

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

以下是套用範本之後,此 CheckBoxUncheckedCheckedIndeterminate 狀態中的外觀。

custom checkbox template

指定控制項的視覺結構

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

此 XAML 會建立 CheckBoxControlTemplate,指定控制項的內容位於選取方塊下方。 根元素是 框線。 此範例會指定要建立 X 路徑,指出使用者已選取 CheckBox,以及指出不確定狀態的 橢圓形。 請注意,不透明度路徑橢圓形上設定為 0,因此預設不會出現。

TemplateBinding 是特殊的繫結,這會將控制項範本中的屬性值連結至範本化控制項上一些其他已公開屬性的值。 TemplateBinding 只能在 XAML 中的 ControlTemplate 定義中使用。 如需詳細資訊,請參閱 TemplateBinding 標記延伸

注意

從 Windows 10 版本 1809 (SDK 17763) 起,您可以使用 x:Bind標記延伸來取代您使用的 TemplateBinding。 如需詳細資訊,請參閱 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 個檢查狀態:CheckedUnchecked,和 IndeterminateIsChecked 屬性的值會決定 CheckBox 的狀態,而其狀態會決定方塊中出現的內容。

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

IsChecked CheckBox 狀態 CheckBox 外觀
true Checked 包含一個 "X"。
false Unchecked 空白。
null Indeterminate 包含圓形。

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

此 XAML 會顯示 CheckedUncheckedIndeterminate 狀態的 VisualState 物件。 此範例會在框線上設定 VisualStateManager.VisualStateGroups 附加屬性,這是 ControlTemplate 的根元素。 CheckedVisualState 指定 Path 名為 CheckGlyph (如前述範例所示) 的 Opacity 是 1。 IndeterminateVisualState 指定 橢圓形 (名為 IndeterminateGlyph ) 的不透明度 是 1。 UncheckedVisualState 沒有 SetterStoryboard,因此 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 物件的運作方式,請考慮 CheckBoxUnchecked狀態到 Checked 狀態,然後到 Indeterminate 狀態,然後回到 Unchecked 狀態時會發生什麼情況。 以下是轉換。

狀態轉換 發生什麼情況 轉換完成時的 CheckBox 外觀
Unchecked 變更為 Checked 會套用 CheckedVisualStateSetter 值,所以 CheckGlyph不透明度為 1。 隨即顯示 X。
Checked 變更為 Indeterminate 會套用 IndeterminateVisualStateSetter 值,所以 IndeterminateGlyph不透明度為 1。 會移除 CheckedVisualStateSetter 值,所以 CheckGlyph不透明度為 0。 隨即顯示圓形。
Indeterminate 變更為 Unchecked 會移除 IndeterminateVisualStateSetter 值,所以 IndeterminateGlyph不透明度為 0。 不會顯示任何東西。

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

使用工具輕鬆地處理主題

將主題套用至控制項的快速方法是以滑鼠右鍵按一下 Microsoft Visual Studio 文件大綱上的控制項,然後選取 [編輯主題][編輯樣式] (視您按一下滑鼠右鍵的控制項而定)。 然後,您可以選取 [套用資源] 套用現有的主題,或選取 [建立空白] 定義新的主題。

控制項和協助工具

當您為控制項建立新的範本時,除了可能變更控制項的行為和視覺外觀之外,您可能也會變更控制項將本身呈現為協助工具架構的方式。 Windows 應用程式支援 Microsoft UI 自動化的協助工具架構。 所有預設控制項及其範本都支援適合控制用途和功能的常見 UI 自動化控制項類型和模式。 這些控制項類型和模式由輔助技術等 UI 自動化用戶端進行解譯,這使得控制項可以作為更大的可存取應用程式 UI 的一部分進行存取。

為了分離基本控制邏輯並滿足 UI 自動化的一些架構需求,控制項類別將其可存取性支援包含在單獨的類別 (自動化對等) 中。 自動化對等有時會與控制項範本互動,因為對等預期範本中有某些具名組件存在,因此可以啟用輔助技術來叫用按鈕動作等功能。

當您建立全新的自訂控制項時,您有時也會想要建立新的自動化對等來配合它。 如需詳細資訊,請參閱自訂自動化對等

深入了解控制項的預設範本

文件中關於 XAML 控制項的樣式和範本的主題會向您展示與之前解釋的編輯主題編輯樣式技術中看到的相同起始 XAML 的摘錄。 每個主題都會列出視覺狀態的名稱、使用的主題資源以及包含範本之樣式的完整 XAML。 如果您已經開始修改範本,並想要查看原始範本的外觀,或確認您的新範本具有所有必要的具名視覺狀態,這些主題可能會很有用。

控制項範本中的主題資源

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

取得範例程式碼