スタイルとテンプレート

更新 : 2007 年 11 月

Windows Presentation Foundation (WPF) のスタイルとテンプレートは、アプリケーション、ドキュメント、またはユーザー インターフェイス (UI) のデザイナが、視覚的に魅力のある効果を作成したり、それらの製品の外観に統一感を持たせることができる一連の機能 (スタイル、テンプレート、トリガ、およびストーリーボード) を表します。作成者やデザイナはアプリケーション単位で広範囲に外観をカスタマイズできますが、アプリケーション内およびアプリケーション間の外観の保守や共有のためには強力なスタイルとテンプレート モデルが必要です。Windows Presentation Foundation (WPF) はそのモデルを備えています。

WPF スタイル モデルのもう 1 つの機能は、プレゼンテーションとロジックの分離です。つまり、デザイナは、開発者が C# または Visual Basic を使用してプログラミング ロジックを作成しているのと同時に、XAML だけを使用してアプリケーションの外観を作成できます。

ここでは、「スタイルとテンプレート サンプルの概要」で扱っているアプリケーションについて説明します。これは、2 つの TextBlock 要素と、イメージのリストにバインドされる 1 つの ListBox コントロールを使用する次のようなアプリケーションです。

スタイル設定された ListView

ここでは、アプリケーションのスタイルとテンプレートの側面に焦点を当て、データ バインディングの概念については説明しません。データ バインディングの詳細については、「データ バインディングの概要」を参照してください。

また、スタイルやテンプレートの再利用を実現できるリソースについて理解することも重要です。リソースの詳細については、「リソースの概要」を参照してください。

このトピックには次のセクションが含まれています。

  • スタイルの基本
  • データ テンプレート
  • コントロール テンプレート
  • トリガ
  • 共有リソースとテーマ
  • 関連トピック

スタイルの基本

Style は、プロパティ値のセットを複数の要素に適用するための便利な方法と考えることができます。たとえば、次の TextBlock 要素があり、その外観が既定の外観であるとします。

<TextBlock>My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>

スタイル サンプル スクリーン ショット

既定の外観は、FontSizeFontFamily などのプロパティを各 TextBlock 要素に直接設定することにより変更できます。ただし、TextBlock 要素で一部のプロパティを共有する場合は、次に示すように、XAML ファイルの Resources セクションに Style を作成することができます。

<Window.Resources>


...


<!--A Style that affects all TextBlocks-->
<Style TargetType="TextBlock">
  <Setter Property="HorizontalAlignment" Value="Center" />
  <Setter Property="FontFamily" Value="Comic Sans MS"/>
  <Setter Property="FontSize" Value="14"/>
</Style>


...


</Window.Resources>

スタイルの TargetTypeTextBlock 型に設定すると、ウィンドウ内のすべての TextBlock 要素にスタイルが適用されます。

これで、TextBlock 要素は次のように表示されます。

スタイル サンプル スクリーン ショット

このセクションには次のサブセクションが含まれています。

  • スタイルの拡張
  • TargetType プロパティと x:Key 属性の関係
  • スタイルとリソース
  • プログラムによるスタイルの設定
  • バインディング、動的リソース、およびイベント ハンドラ

スタイルの拡張

2 つの TextBlock 要素で、FontFamily や中央揃えの HorizontalAlignment など一部のプロパティ値を共有する可能性がありますが、テキスト "My Pictures" にプロパティを追加する必要もあります。これを行うには、次に示すように、最初のスタイルに基づく新しいスタイルを作成します。

<Window.Resources>


...


<!--A Style that extends the previous TextBlock Style-->
<!--This is a "named style" with an x:Key of TitleText-->
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
       TargetType="TextBlock"
       x:Key="TitleText">
  <Setter Property="FontSize" Value="26"/>
  <Setter Property="Foreground">
  <Setter.Value>
      <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
        <LinearGradientBrush.GradientStops>
          <GradientStop Offset="0.0" Color="#90DDDD" />
          <GradientStop Offset="1.0" Color="#5BFFFF" />
        </LinearGradientBrush.GradientStops>
      </LinearGradientBrush>
    </Setter.Value>
  </Setter>
</Style>


...


</Window.Resources>

上記のスタイルでは x:Key が指定されています。スタイルを適用するには、次に示すように、TextBlockStyle プロパティを x:Key 値に設定します。

<TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>

この TextBlock スタイルでは、HorizontalAlignment の値が Center に、FontFamily の値が Comic Sans MS に、FontSize の値が 26 に、Foreground の値が上記の例で示した LinearGradientBrush に設定されています。この例では、基本スタイルの FontSize 値をオーバーライドしていることに注意してください。Style に同じプロパティを設定する Setter が複数ある場合は、最後に宣言した Setter が優先されます。

TextBlock 要素は、次のような外観になります。

スタイル設定された TextBlocks

この TitleText スタイルは、TextBlock 型に対して作成されたスタイルを拡張します。また、x:Key 値を使用して、x:Key を持つスタイルも拡張できます。具体的な方法については、BasedOn プロパティで示されている例を参照してください。

TargetType プロパティと x:Key 属性の関係

最初の例に示したように、x:Key でスタイルを割り当てずに TargetType プロパティを TextBlock に設定すると、スタイルはすべての TextBlock 要素に適用されます。この場合、x:Key は暗黙的に {x:Type TextBlock} に設定されます。x:Key 値を明示的に {x:Type TextBlock} 以外の値に設定すると、この Style がすべての TextBlock 要素に自動的に適用されなくなります。代わりに、x:Key 値を使用して、このスタイルを明示的に TextBlock 要素に適用する必要があります。スタイルがリソース セクション内にあり、スタイルに TargetType プロパティを設定しない場合は、x:Key を指定する必要があります。

x:Key の既定値を設定するだけでなく、TargetType プロパティで、setter のプロパティを適用する型を指定します。TargetType を指定しない場合は、Property="ClassName.Property" 構文を使用して、Setter オブジェクトのプロパティをクラス名で修飾する必要があります。たとえば、Property="FontSize" の代わりに、Property を "TextBlock.FontSize" または "Control.FontSize" に設定する必要があります。

また、多くの WPF コントロールは、他の WPF コントロールの組み合わせで構成されます。特定の型のすべてのコントロールに適用するスタイルを作成すると、予期しない結果になる可能性があります。たとえば、Window 内の TextBlock 型を対象とするスタイルを作成すると、そのスタイルは、別のコントロール (ListBox など) の一部である TextBlock も含め、ウィンドウ内のすべての TextBlock コントロールに適用されます。

スタイルとリソース

FrameworkElement または FrameworkContentElement から派生する任意の要素に対してスタイルを使用できます。最も一般的なスタイルの宣言方法は、前の例で示したように、XAML ファイル内の Resources セクションでリソースとして宣言することです。スタイルはリソースであるため、すべてのリソースに適用されるスコープ規則が適用されます。したがって、スタイルをどこで宣言するかは、スタイルの適用対象に影響します。たとえば、アプリケーション定義 XAML ファイルのルート要素でスタイルを宣言すると、そのスタイルはアプリケーション内のあらゆる場所で使用できます。一方、ナビゲーション アプリケーションを作成する場合に、アプリケーションのいずれかの XAML ファイルで宣言したスタイルは、その XAML ファイルでしか使用できません。リソースのスコープ規則の詳細については、「リソースの概要」を参照してください。

また、スタイルとリソースの詳細については、この概要の「共有リソースとテーマ」を参照してください。

プログラムによるスタイルの設定

プログラムで名前付きのスタイルを要素に割り当てるには、リソース コレクションからスタイルを取得して、要素の Style プロパティに割り当てます。リソース コレクション内の項目は Object 型です。したがって、取得したスタイルを Style にキャストしてから Style プロパティに割り当てる必要があります。たとえば、定義済みの TitleText スタイルを、textblock1 という名前の TextBlock に設定するには、次のコードを実行します。

textblock1.Style = (Style)(this.Resources["TitleText"]);

スタイルが適用されると、シールされて、変更できません。既に適用されているスタイルを動的に変更する場合は、新しいスタイルを作成して既存のスタイルを置き換える必要があります。詳細については、IsSealed プロパティを参照してください。

カスタム ロジックに基づいて適用するスタイルを選択するオブジェクトを作成できます。具体的な方法については、StyleSelector クラスで示されている例を参照してください。

バインディング、動的リソース、およびイベント ハンドラ

Setter.Value プロパティを使用して、バインディングのマークアップ拡張機能または DynamicResource のマークアップ拡張機能を指定できます。詳細については、Setter.Value プロパティの例を参照してください。

ここまでは、setter を使用したプロパティ値の設定について説明してきました。スタイルではイベント ハンドラも指定できます。詳細については、EventSetter のトピックを参照してください。

データ テンプレート

このサンプル アプリケーションでは、写真のリストにバインドされる ListBox コントロールを使用します。

<ListBox ItemsSource="{Binding Source={StaticResource MyPhotos}}"
         Background="Silver" Width="600" Margin="10" SelectedIndex="0"/>

ListBox の現在の外観は次のとおりです。

テンプレート適用前の ListBox

ほとんどのコントロールはある型のコンテンツを使用し、そのコンテンツの多くはバインド先のデータから取得しています。このサンプルでは、データは写真のリストです。WPF では、DataTemplate を使用して、データの視覚的表現を定義します。基本的に、DataTemplate に挿入する内容によって、レンダリングされるアプリケーションでのデータの外観が決まります。

このサンプル アプリケーションでは、各カスタム Photo オブジェクトは、イメージのファイル パスを指定する文字列型の Source プロパティを 1 つ持っています。現在、写真オブジェクトはファイル パスとして表示されています。

写真をイメージとして表示するには、DataTemplate をリソースとして作成します。

<Window.Resources>


...


<!--DataTemplate to display Photos as images
    instead of text strings of Paths-->
<DataTemplate DataType="{x:Type local:Photo}">
  <Border Margin="3">
    <Image Source="{Binding Source}"/>
  </Border>
</DataTemplate>


...


</Window.Resources>

DataType プロパティは、StyleTargetType プロパティと非常に似ています。DataTemplate がリソース セクション内にある場合に、DataType プロパティをある型に指定し、それを x:Key に割り当てると、その型が表示されるたびに DataTemplate が適用されます。x:Key で DataTemplate を割り当ててから、ItemTemplate プロパティや ContentTemplate プロパティなど、DataTemplate 型を取るプロパティの StaticResource として設定するオプションを常に使用できます。

基本的に、上記の例の DataTemplate は、Photo オブジェクトが存在するときは常に、そのオブジェクトが Border 内の Image として表示されることを定義します。この DataTemplate を使用すると、この例のアプリケーションの外観は次のようになります。

フォト イメージ

データ テンプレート モデルには他の機能もあります。たとえば、MenuTreeView などの HeaderedItemsControl 型を使用して他のコレクションを格納するコレクション データを表示している場合は、HierarchicalDataTemplate が存在します。別のデータ テンプレート機能として、カスタム ロジックに基づいて使用する DataTemplate を選択できる DataTemplateSelector があります。詳細については、「データ テンプレートの概要」を参照してください。このトピックでは、さまざまなデータ テンプレート機能について詳しく説明しています。

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

このセクションには次のサブセクションが含まれています。

  • ControlTemplate を使用しない
  • ControlTemplate とは
  • ControlTemplate の作成
  • IsItemsHost プロパティ
  • ItemsPresenter と ContentPresenter
  • TemplateBinding

写真をイメージとして表示できたので、これらの写真を垂直ではなく水平に表示してみましょう。ListBox を水平にする必要があります。

ControlTemplate を使用しない

最初に、ControlTemplate を使用して ListBox を水平にする必要がないことに注意することが重要です。ListBox には、ItemsPanelTemplate、つまり ListBox の項目のレイアウトを制御するテンプレートを設定できる ItemsPanel プロパティがあります。ListBox スタイルを単純に作成し、ItemsPanel プロパティを設定するという 1 つのオプションを次の例に示します。

<Style TargetType="ListBox">
  <Setter Property="ItemsPanel">
    <Setter.Value>
      <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal"
                    VerticalAlignment="Center"
                    HorizontalAlignment="Center"/>
      </ItemsPanelTemplate>
    </Setter.Value>
  </Setter>
</Style>

これは適切に機能し、水平の ListBox が作成されます。この例は、シナリオに応じて、ControlTemplate を単に置き換えるだけではなく、それ以外のオプションも実行できることを表しています。この例では、丸い角など追加のプロパティを持つ水平の ListBox が必要な場合、ListBoxControlTemplate を使用する必要があります。

実行方法の例を示す前に、ControlTemplate の概念を最初に説明することが重要です。

ControlTemplate とは

多くのコントロールには、外観と動作が存在します。たとえば、ボタンの場合、外観は押すことができる浮き上がった領域で、動作はクリックに応じて発生する Click イベントです。

必要な動作は提供しても、必要な外観は示さないコントロールが存在する場合があります。ここまでは、スタイル setter を使用して、コントロールの外観に影響するプロパティ値を設定する方法を説明してきました。ただし、コントロールの構造を変更したり、コントロールを構成するコンポーネントにプロパティ値を設定するには、ControlTemplate を使用する必要があります。

WPF では、コントロールの ControlTemplate で、コントロールの外観を定義します。コントロールの構造や外観を変更するには、そのコントロールの新しい ControlTemplate を定義します。多くの場合、この方法には十分な柔軟性があるため、独自のカスタム コントロールを作成する必要がありません。コントロールに対して独自の ControlTemplate を定義しない場合は、システム テーマに一致する既定のテンプレートを取得します。このテンプレートは、Button コントロールにその既定の外観を与えます。

注意すべきなのは、コントロールに対して ControlTemplate を作成すると、ControlTemplate 全体が置き換わるという点です。たとえば、ButtonControlTemplate を次のように定義できます。

ContentPresenter 要素は、ButtonContent が移動する場所を単純にマークします。詳細については、後のセクションで説明します。

<Style TargetType="Button">
  <!--Set to true to not get any properties from the themes.-->
  <Setter Property="OverridesDefaultStyle" Value="True"/>
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Grid>
          <Ellipse Fill="{TemplateBinding Background}"/>
          <ContentPresenter HorizontalAlignment="Center"
                            VerticalAlignment="Center"/>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

これが適用されると、ButtonEllipse として表示されます。

ボタン ControlTemplate のサンプル

Button にフォーカスがある状態または押された状態でどのように見えるかはすべて、置き換えるボタンの既定の外観の一部であることに注意してください。このため、ボタンが押された場合の外観は、必要に応じて定義に含めることができます。コード例全体については、「Button ControlTemplate の例」を参照してください。

ControlTemplate を作成している場合は、最初に「ControlTemplate の例」に示されている例を使用することをお勧めします。実際にコントロールを構成しているパーツを確認する必要がある場合は、「テーマ」に示されているテーマ ファイルを参照するか、XAMLPad の Show Visual Tree 機能を使用できます。XAMLPad は、Windows ソフトウェア開発キット (SDK) と共にインストールされるアプリケーションです。

ControlTemplate の作成

引き続き同じ例を使って、水平で角が丸い ListBox を定義する ControlTemplate を作成してみましょう。コントロールの ControlTemplate を置き換えるには、Template プロパティを新しい ControlTemplate に設定します。

<Style TargetType="ListBox">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ListBox">
        <Border CornerRadius="5" Background="{TemplateBinding ListBox.Background}">
          <ScrollViewer HorizontalScrollBarVisibility="Auto">
            <StackPanel Orientation="Horizontal"
                       VerticalAlignment="Center"
                       HorizontalAlignment="Center"
                       IsItemsHost="True"/>
          </ScrollViewer>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

このように Template プロパティを設定するのは、Style を使用して他のコントロール プロパティを設定するのと変わりありません。Style をツールとして使用すると、Template プロパティを設定するのに役立ちます。つまり、ControlTemplate を設定する別の方法として、コントロールで Template プロパティを直接設定する方法があります。この方法で実行する場合は、Resources セクションで ControlTemplate を作成し、それを x:Key で指定して、静的リソースとして使用します。例については、Template プロパティのトピックを参照してください。

上記の例でわかるように、ControlTemplate クラスには、Style クラスの TargetType プロパティと同様の TargetType プロパティがあります。ただし、StyleDataTemplate とは異なり、ControlTemplate オブジェクトには、暗黙のキーの概念がありません。つまり、スタンドアロンの ControlTemplate があり、TargetType プロパティが 1 つの型に設定されている場合、ControlTemplate は自動的にはその型に適用されません。また、テンプレート定義に ContentPresenter が含まれている場合、ControlTemplateTargetType プロパティが必要になることにも注意してください。

ControlTemplate を使用してみてください。たとえば、StackPanelWrapPanel に置き換え、ScrollViewerHorizontalScrollBarVisibility プロパティを Disabled に設定し、ListBox の幅を 300 に設定します (WrapPanel は、最初の行がスペースを使い果たした場合にのみ項目を次の行に挿入します。ScrollViewerHorizontalScrollBarVisibility プロパティを Disabled に設定しない場合、末尾までスクロールできるので、最初の行はスペースを使い果たしません。その結果、WrapPanel は項目を折り返しません)。

IsItemsHost プロパティ

この例では、1 つの重要なプロパティとして、IsItemsHost プロパティが必要です。IsItemsHost プロパティは、ItemsControl (項目のリストを処理する ListBox などのコントロール) のテンプレート内で、生成された要素が移動する場所を示すために使用されます。StackPanel でこのプロパティを true に設定すると、ListBox に追加されたすべての項目が StackPanel に移動します。このプロパティは Panel 型でのみ機能することに注意してください。

ItemsPresenter と ContentPresenter

ただし、ControlTemplate でパネルを指定し、それをこの方法で IsItemsHost としてマークすると、コントロールのユーザーは、ControlTemplate を使用せずに ItemsPanel を置き換えることはできません。したがって、この方法で指定するのは、テンプレートを使用せずにパネルを置き換えることがない場合のみにしてください。または、ItemsPresenter 要素を使用して、項目が移動する場所をマークしてから、ItemsPanel プロパティを設定して ItemsPanelTemplate を指定します。ItemsPanelTemplate のページには、この方法を示す例があります。ItemsPresenter を使用する別の例については、「TreeView ControlTemplate の例」を参照してください。

Button などの ContentControl のテンプレートを作成している場合は、対応する要素が ContentPresenter になります。同様に、ContentControl 型の ControlTemplate にこの要素を配置して、コンテンツが表示される場所を示します。これについては、「ControlTemplate とは」に例があります。その他の例については、「Label ControlTemplate の例」および「ListBoxItem ControlTemplate の例」を参照してください。

TemplateBinding

前の例で注意すべきもう 1 つの重要な点は、{TemplateBinding ListBox.Background} に設定されている Background 値です。これは単純に、BorderBackground を、ListBox で設定された Background 値と同期する必要があることを示します。TemplateBinding は、Binding に似ています。実際、TemplateBinding は、Binding よりも効率的ですが機能は劣ります。TemplateBinding を使用することは、Source プロパティを RelativeSource.TemplatedParent に設定して Binding を使用することと同じです。

コントロールのユーザーが特定のプロパティの値を制御できるようにする場合は、ControlTemplate で TemplateBinding を使用します。TemplateBinding は、TemplateBindingExtension クラスで表されるマークアップ拡張機能です。

DataTemplate および ControlTemplate は、それらのコンテンツがオブジェクトの視覚化になるという点で似ています。ListBox ControlTemplate 定義を使用すると、アプリケーションの外観は次のようになります。

スタイル サンプル スクリーン ショット

トリガ

StyleControlTemplate、および DataTemplate はすべて、トリガのセットを含むことができる Triggers プロパティを持っています。プロパティ値が変更したり、イベントが発生すると、トリガはプロパティを設定するか、アニメーションなどのアクションを開始します。

このセクションには次のサブセクションが含まれています。

  • プロパティ トリガ
  • EventTrigger とストーリーボード
  • MultiTrigger、DataTrigger、および MultiDataTrigger

プロパティ トリガ

トリガを使用してプロパティを設定する方法を示すために、各 ListBoxItem を、選択されない場合は部分的に透明にしてみます。

次のスタイルでは、ListBoxItemOpacity 値を 0.5 に設定しています。ただし、IsSelected プロパティが true の場合は、Opacity が 1.0 に設定されます。

<Style TargetType="ListBoxItem">
  <Setter Property="Opacity" Value="0.5" />
  <Setter Property="MaxHeight" Value="75" />
  <Style.Triggers>
    <Trigger Property="IsSelected" Value="True">
        <Setter Property="Opacity" Value="1.0" />
    </Trigger>


...


  </Style.Triggers>
</Style>

この例では、Trigger を使用してプロパティ値を設定しますが、Trigger クラスには、トリガでアクションを実行できる EnterActions プロパティと ExitActions プロパティもあります。

ListBoxItemMaxHeight プロパティを 75 にも設定しています。次のスクリーンショットでは、3 つ目の項目が選択された項目です。

スタイル設定された ListView

EventTrigger とストーリーボード

Trigger でプロパティ値を設定するか、プロパティの値に基づいてアクションを開始することを説明しました。もう 1 つの型のトリガは、イベントの発生に基づいて一連のアクションを開始する EventTrigger です。たとえば、次の EventTrigger オブジェクトは、マウス ポインタが ListBoxItem に入ると、MaxHeight プロパティが 0.2 秒間 90 の値にアニメーション化することを指定します。マウスが項目から離れると、プロパティは、1 秒間、元の値に戻ります。MouseLeave アニメーションに対して To 値を指定する必要がない理由に注意してください。これは、アニメーションが元の値を追跡できるからです。

<EventTrigger RoutedEvent="Mouse.MouseEnter">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Duration="0:0:0.2"
          Storyboard.TargetProperty="MaxHeight"
          To="90"  />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
  <EventTrigger.Actions>
    <BeginStoryboard>
      <Storyboard>
        <DoubleAnimation
          Duration="0:0:1"
          Storyboard.TargetProperty="MaxHeight"  />
      </Storyboard>
    </BeginStoryboard>
  </EventTrigger.Actions>
</EventTrigger>

詳細については、「ストーリーボードの概要」を参照してください。

次のスクリーンショットでは、マウスが 3 つ目の項目をポイントしています。

スタイル サンプル スクリーン ショット

MultiTrigger、DataTrigger、および MultiDataTrigger

TriggerEventTrigger に加え、他の型のトリガもあります。MultiTrigger を使用して、複数の条件に基づいてプロパティ値を設定できます。条件のプロパティがデータ バインドされている場合は、DataTrigger および MultiDataTrigger を使用します。

ここで説明したサンプル全体については、「スタイルとテンプレート サンプルの概要」を参照してください。

共有リソースとテーマ

一般的な Windows Presentation Foundation (WPF) アプリケーションには、アプリケーション全体に適用される複数のユーザー インターフェイス (UI) リソースが含まれる場合があります。まとめると、このリソースのセットは、アプリケーションのテーマと見なすことができます。Windows Presentation Foundation (WPF) は、ResourceDictionary クラスとしてカプセル化されたリソース ディクショナリを使用して、テーマとしてユーザー インターフェイス (UI) リソースのパッケージ化をサポートします。

Windows Presentation Foundation (WPF) テーマは、要素のビジュアルをカスタマイズするために Windows Presentation Foundation (WPF) が公開するスタイルとテンプレート機構を使用して定義されます。

Windows Presentation Foundation (WPF) テーマ リソースは、埋め込みのリソース ディクショナリに格納されます。これらのリソース ディクショナリは、署名付きアセンブリ内に埋め込む必要があります。コードそのものと同じアセンブリに埋め込むことも、side-by-side アセンブリに埋め込むこともできます。PresentationFramework.dll (Windows Presentation Foundation (WPF) コントロールを含むアセンブリ) では、テーマ リソースが一連の side-by-side アセンブリ内にあります。

テーマは、要素のスタイルを検索するときの最終停止位置になります。通常、検索は、最初に該当のリソースを検索する要素ツリーをウォークしてから、アプリケーション リソース コレクション内を探し、最後にシステムを照会します。この方法により、アプリケーション作成者は、テーマに到達する前にツリーまたはアプリケーション レベルで任意のオブジェクトのスタイルを再定義できます。

リソース ディクショナリは、複数のアプリケーションで 1 つのテーマを再利用できる個々のファイルとして定義できます。また、リソースの種類は同じでも値が異なる複数のリソース ディクショナリを定義して、入れ替え可能なテーマを作成することもできます。アプリケーション レベルでこれらのスタイルまたは他のリソースを再定義する方法は、アプリケーションをスキニングする場合に推奨される方法です。

スタイルとテンプレートを含む一連のリソースをアプリケーション間で共有するためには、XAML ファイルを作成し、ResourceDictionary を定義します。たとえば、「ControlTemplate を使用したスタイル設定のサンプル」の一部を示す次のスクリーンショットを見てください。

ControlTemplate の例

サンプル内の XAML ファイルを見ると、すべてのファイルに次のコードが含まれていることがわかります。

<ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="Shared.xaml" />
</ResourceDictionary.MergedDictionaries>

これは、サンプル内のコントロールを一貫性のある外観にするための一連のスタイル リソースやブラシ リソースを含む ResourceDictionary を定義する shared.xaml の共有です。

詳細については、「マージされたリソース ディクショナリ」を参照してください。

カスタム コントロールのテーマを作成する場合は、「コントロールの作成の概要」の「外部のコントロール ライブラリ」を参照してください。

参照

処理手順

方法 : ControlTemplate によって生成された要素を検索する

方法 : DataTemplate によって生成された要素を検索する

Photo Store のデモ

概念

Windows Presentation Foundation におけるパッケージの URI

その他の技術情報

テーマ