コントロール テンプレート

XAML フレームワークでコントロール テンプレートを作成することで、コントロールのビジュアル構造と視覚的な動作をカスタマイズできます。 コントロールには、 BackgroundForegroundFontFamily など、コントロールの外観のさまざまな側面を指定するように設定できる多くのプロパティがあります。 ただし、これらのプロパティを設定することで行うことができる変更は制限されます。 ControlTemplate クラスを使用してテンプレートを作成することで、追加のカスタマイズを指定できます。 ここでは、 ControlTemplate を作成して、 CheckBox コントロールの外観をカスタマイズする方法について説明します。

重要な API: ControlTemplate クラスControl.Template プロパティ

カスタム コントロール テンプレートの例

既定では、 CheckBox コントロールは、そのコンテンツ (文字列またはオブジェクトを CheckBox の横にあるオブジェクト) を選択ボックスの右側に配置し、チェック マークはユーザーが CheckBox を選択したことを示します。 これらの特性は、 CheckBoxの視覚的な構造と視覚的な動作を表します。

UncheckedChecked、およびIndeterminateの状態に示されている既定の ControlTemplate を使用したCheckBox を次に示します。

既定のチェック ボックス テンプレート

これらの特性を変更するには、CheckBoxControlTemplateを作成します。 たとえば、チェック ボックスの内容を選択ボックスの下に表示し、 X を使用してユーザーがチェック ボックスをオンにしたことを示す場合です。 これらの特性は、CheckBoxControlTemplate で指定します。

コントロールでカスタム テンプレートを使用するには、コントロールの Template プロパティに ControlTemplate を割り当てます。 CheckBoxTemplate1と呼ばれる ControlTemplate を使用するCheckBoxを次に示します。 次のセクションでは、 ControlTemplate の拡張アプリケーション マークアップ言語 (XAML) を示します。

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

テンプレートを適用した後、この CheckBoxUncheckedChecked、および Indeterminate の状態でどのように表示されるかを次に示します。

カスタム チェックボックス テンプレート

コントロールのビジュアル構造を指定する

ControlTemplate を作成するときは、FrameworkElement オブジェクトを組み合わせて 1 つのコントロールを構築します。 ControlTemplateのルート要素として必要なFrameworkElementは 1 つだけです。 ルート要素には、通常、他の FrameworkElement オブジェクトが含まれています。 複数のオブジェクトを組み合わせて、コントロールの視覚的な構造を構成します。

この XAML は、コントロールの内容が選択ボックスの下にあることを指定するCheckBoxControlTemplateを作成します。 ルート要素は Border です。 この例では、Path を指定して、ユーザーが CheckBox を選択したことを示す X を作成し、不確定状態を示す Ellipse を作成します。 Path では Opacity が 0 に設定されEllipse既定ではどちらも表示されません。

TemplateBinding は、コントロール テンプレート内のプロパティの値を、テンプレート化されたコントロールの他の公開プロパティの値にリンクする特殊なバインドです。 XAML では、TemplateBinding は ControlTemplate 定義内でのみ使用できます。 詳細については、「 TemplateBinding マークアップ拡張機能 を参照してください。

Note

Windows 10 Version 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 コントロールには、CheckedUncheckedIndeterminateの 3 つのチェック状態があります。 IsCheckedプロパティの値は、CheckBoxの状態を決定し、その状態はボックスに表示される内容を決定します。

次の表に、 IsCheckedの使用可能な値、 CheckBoxの対応する状態、および CheckBoxの外観を示します。

IsChecked CheckBox 状態 CheckBox の外観
true Checked "X" を含みます。
false Unchecked 空白。
[Null] Indeterminate 円を含みます。

コントロールが特定の状態にある場合は、 VisualState オブジェクトを使用して、コントロールの外観を指定します。 VisualStateには、ControlTemplate内の要素の外観を変更するSetterまたはStoryboardが含まれています。 コントロールが VisualState.Name プロパティで指定した状態になると、 Setter または Storyboard でプロパティが変更されます。 コントロールが状態を終了すると、変更は削除されます。 VisualState オブジェクトを VisualStateGroup オブジェクトに追加します。 ControlTemplateのルート FrameworkElementに設定したVisualStateManager.VisualStateGroups 添付プロパティにオブジェクトVisualStateGroupを追加します。

この XAML は、CheckedUnchecked、およびIndeterminate状態のVisualState オブジェクトを示します。 この例では、 VisualStateManager.VisualStateGroups 添付プロパティを Border に設定します。これは、 ControlTemplate のルート要素です。 Checked VisualState は、(前の例で示した) CheckGlyph という名前の PathOpacity が 1 であることを指定します。 Indeterminate VisualState は、IndeterminateGlyph という名前の EllipseOpacity が 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 オブジェクトがどのように動作するかを理解するには、CheckBoxUnchecked状態からChecked状態に移行してから、Indeterminate状態に戻り、Unchecked状態に戻ったときに何が起こるかを検討します。 遷移を次に示します。

状態の変化 起こること 切り替えが完了したときの CheckBox の外観
Unchecked から Checked Checked VisualStateSetter 値が適用され、CheckGlyphOpacity が 1 となる。 X が表示されます。
Checked から Indeterminate Indeterminate VisualStateSetter 値が適用され、IndeterminateGlyphOpacity が 1 となる。 Checked VisualStateSetter 値が削除され、CheckGlyphOpacity が 0 となる。 円が表示されます。
Indeterminate から Unchecked Indeterminate VisualStateSetter 値が削除され、IndeterminateGlyphOpacity が 0 となる。 何も表示されません。

  コントロールの表示状態を作成する方法、特に Storyboard クラスとアニメーションの種類の使用方法の詳細については、「 表示状態のストーリーボードアニメーションを参照してください。

ツールを使用してテーマを簡単に操作する

テーマをコントロールに簡単に適用するには、Microsoft Visual Studio Document アウトラインのコントロールを右クリックし編集テーマまたは編集スタイル (右クリックするコントロールに応じて) を選択します。 その後、 Apply Resource を選択して既存のテーマを適用するか、[空 作成] を選択して新しいテーマを定義

コントロールとアクセシビリティ

コントロールの新しいテンプレートを作成するときに、コントロールの動作や視覚的な外観を変更するだけでなく、コントロール自体の表現方法をアクセシビリティ フレームワークに変更する場合もあります。 Windows アプリでは、アクセシビリティのための Microsoft UI オートメーション フレームワークがサポートされています。 既定のコントロールとそのテンプレートはすべて、コントロールの目的と機能に適した一般的なUI オートメーション コントロールの種類とパターンをサポートしています。 これらのコントロールの種類とパターンは支援技術などのUI オートメーションクライアントによって解釈され、これにより、より大きなアクセシビリティ対応アプリ UI の一部としてコントロールにアクセスできるようになります。

基本的な制御ロジックを分離し、UI オートメーションのアーキテクチャ要件の一部を満たすために、コントロール クラスには、別のクラスであるオートメーション ピアでのアクセシビリティサポートが含まれます。 オートメーション ピアは、特定の名前付きパーツがテンプレートに存在することを想定しているため、コントロール テンプレートとの対話を行う場合があります。そのため、支援技術によるボタンのアクションの呼び出しを可能にするなどの機能が可能になります。

まったく新しいカスタム コントロールを作成するときに、新しいオートメーション ピアを作成して同じ操作を行う必要がある場合もあります。 詳細については、「 Custom オートメーション ピア」を参照してください。

コントロールの既定のテンプレートの詳細を確認する

XAML コントロールのスタイルとテンプレートについて説明するトピックでは、前に説明した Edit Theme または Edit Style 手法を使用した場合と同じ開始 XAML の抜粋を示します。 各トピックでは、表示状態の名前、使用されるテーマ リソース、テンプレートを含むスタイルの完全な XAML を一覧表示します。 このトピックは、テンプレートの変更を既に開始していて、元のテンプレートの外観を確認する場合や、新しいテンプレートに必要なすべての名前付き表示状態があることを確認する場合に役立つガイダンスです。

コントロール テンプレートのテーマ リソース

XAML の例の一部の属性では、 {ThemeResource} マークアップ拡張を使用するリソース参照に気付いたかもしれません。 これは、1 つのコントロール テンプレートで、現在アクティブなテーマに応じて異なる値を指定できるリソースを使用できるようにする手法です。 テーマの主な目的は、システム全体に暗いテーマ、明るいテーマ、ハイ コントラスト テーマのどちらを適用するかをユーザーが選択できるようにすることであるため、これはブラシと色にとって特に重要です。 XAML リソース システムを使用するアプリでは、そのテーマに適したリソース セットを使用できます。そのため、アプリの UI のテーマの選択は、ユーザーのシステム全体のテーマの選択を反映します。

サンプル コードの入手