コントロールのスタイルを作成する方法 (WPF .NET)
Windows Presentation Foundation (WPF) を使用すると、独自の再利用可能なスタイルを使用して、既存のコントロールの外観をカスタマイズできます。 スタイルは、アプリ、ウィンドウ、ページにグローバルに適用することも、コントロールに直接適用することもできます。
スタイルの作成
Style は、一連のプロパティ値を 1 つ以上の要素に適用する便利な方法と考えることができます。 FrameworkElement または FrameworkContentElement から派生する任意の要素 (Window や Button など) にスタイルを使用できます。
スタイルを宣言する最も一般的な方法は、XAML ファイルの Resources
セクションでリソースとして行うものです。 スタイルはリソースであるため、すべてのリソースに適用されるものと同じスコープ規則に従います。 つまり、スタイルを宣言する場所は、スタイルを適用できる場所に影響するということです。 たとえば、アプリ定義の XAML ファイルのルート要素でスタイルを宣言すると、そのスタイルはアプリ内のどこでも使用できます。
<Application x:Class="IntroToStylingAndTemplating.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:IntroToStylingAndTemplating"
StartupUri="WindowExplicitStyle.xaml">
<Application.Resources>
<ResourceDictionary>
<Style x:Key="Header1" TargetType="TextBlock">
<Setter Property="FontSize" Value="15" />
<Setter Property="FontWeight" Value="ExtraBold" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
スタイルをアプリの XAML ファイルのいずれかで宣言すると、そのスタイルはその XAML ファイルでのみ使用できます。 リソースのスコープ規則の詳細については、XAML リソースの概要に関するページを参照してください。
<Window x:Class="IntroToStylingAndTemplating.WindowSingleResource"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:IntroToStylingAndTemplating"
mc:Ignorable="d"
Title="WindowSingleResource" Height="450" Width="800">
<Window.Resources>
<Style x:Key="Header1" TargetType="TextBlock">
<Setter Property="FontSize" Value="15" />
<Setter Property="FontWeight" Value="ExtraBold" />
</Style>
</Window.Resources>
<Grid />
</Window>
スタイルは、スタイルが適用される要素のプロパティを設定する <Setter>
子要素で構成されます。 上記の例では、TextBlock
属性を使用して TargetType
の型に適用するようにスタイルが設定されていることに注意してください。 このスタイルは、FontSize を 15
に設定し、FontWeight を ExtraBold
に設定します。 スタイルが変更するプロパティごとに <Setter>
を追加します。
スタイルを暗黙的に適用する
Style は、一連のプロパティ値を複数の要素に適用する便利な方法です。 たとえば、次の TextBlock 要素と、ウィンドウでのその既定の外観について考えてみます。
<StackPanel>
<TextBlock>My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>
各 FontSize 要素に FontFamily や TextBlockなどのプロパティを直接設定することにより、既定の外観を変更できます。 ただし、TextBlock の要素でいくつかのプロパティを共有する場合は、次に示すように、XAML ファイルの Style セクションに Resources
を作成できます。
<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>
スタイルの TargetType を TextBlock 型に設定し、x:Key
属性を省略すると、そのスタイルにスコープ指定されているすべての TextBlock 要素 (通常、XAML ファイル自体) にスタイルが適用されます。
これにより、TextBlock 要素は次のように表示されます。
スタイルを明示的に適用する
値が含まれる x:Key
属性をスタイルに追加すると、そのスタイルは TargetType のすべての要素に暗黙的に適用されなくなります。 スタイルを明示的に参照する要素だけに、スタイルが適用されます。
次に示すのは、前のセクションのスタイルですが、x:Key
属性を使用して宣言されています。
<Window.Resources>
<Style x:Key="TitleText" TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="14"/>
</Style>
</Window.Resources>
スタイルを適用するには、次に示すように、Style を使用して、要素の x:Key
プロパティを 値に設定します。
<StackPanel>
<TextBlock Style="{StaticResource TitleText}">My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>
最初の TextBlock 要素にはスタイルが適用され、2 番目の TextBlock 要素は未変更のままであることに注意してください。 前のセクションの暗黙的なスタイルは、x:Key
属性を宣言したスタイルに変更されました。つまり、このスタイルの影響を受ける要素は、スタイルを直接参照したものだけであるということです。
スタイルは明示的または暗黙的に適用されると、シールされて、変更できなくなります。 適用されているスタイルを変更する場合は、新しいスタイルを作成して、既存のスタイルを置き換えてください。 詳細については、IsSealed プロパティを参照してください。
カスタム ロジックに基づいて適用するスタイルを選択するオブジェクトを作成できます。 例については、StyleSelector クラスで提供されている例を参照してください。
プログラムを使用してスタイルを適用する
プログラムを使用して名前付きスタイルを要素に割り当てるには、リソース コレクションからスタイルを取得し、それを要素の Style プロパティに割り当てます。 リソース コレクションの項目は Object 型です。 そのため、取得したスタイルは、System.Windows.Style プロパティに割り当てる前に Style
にキャストする必要があります。 たとえば、次のコードは、TextBlock
という名前の textblock1
のスタイルを、定義されているスタイル TitleText
に設定します。
textblock1.Style = (Style)Resources["TitleText"];
textblock1.Style = CType(Resources("TitleText"), Windows.Style)
スタイルを拡張する
たとえば、2 つの TextBlock 要素で、FontFamily や中央揃えされた HorizontalAlignment などのいくつかのプロパティ値を共有する必要がある場合があります。 しかし、同時に、My Pictures というテキストにいくつかの追加プロパティを持たせる必要もあります。 次に示すように、これは、最初のスタイルに基づく新しいスタイルを作成することで実現できます。
<Window.Resources>
<!-- .... other 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>
<!--A Style that extends the previous TextBlock 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>
次に、スタイルを TextBlock
に適用します。
<StackPanel>
<TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>
</StackPanel>
例に示されているように、現在、この TextBlock
スタイルは中央揃えされており、サイズ Comic Sans MS
の 26
フォントを使用し、前景色は LinearGradientBrush に設定されています。 基本スタイルの FontSize 値がオーバーライドされていることに注意してください。 同じプロパティを指す Setter が Style に複数ある場合は、最後に宣言された Setter
が優先されます。
TextBlock 要素が現在どのように表示されるかを次に示します。
この TitleText
スタイルは、TextBlock で参照される、BasedOn="{StaticResource {x:Type TextBlock}}"
型に対して作成されているスタイルを拡張します。 スタイルの x:Key
を使用して x:Key
を持つスタイルを拡張することもできます。 たとえば、Header1
という名前のスタイルがあり、そのスタイルを拡張する必要がある場合は、BasedOn="{StaticResource Header1}"
を使用します。
TargetType プロパティと X:key 属性の関係
前述のように、スタイルに TargetType を割り当てずに TextBlock
プロパティを x:Key
に設定すると、すべての TextBlock 要素にそのスタイルが適用されます。 ここでは、x:Key
は暗黙的に {x:Type TextBlock}
に設定されます。 これは、x:Key
値を {x:Type TextBlock}
以外の値に明示的に設定すると、Style はすべての TextBlock
要素には自動的に適用されないことを意味します。 代わりに、(x:Key
の値を使用して) スタイルを TextBlock
要素に明示的に適用する必要があります。 スタイルがリソース セクションにあり、スタイルに TargetType
プロパティを設定していない場合は、x:Key
属性を設定する必要があります。
x:Key
プロパティは、TargetType
の既定値を提供するだけでなく、セッター プロパティが適用される型を指定します。 TargetType
を指定しない場合は、Setter の構文を使用して、Property="ClassName.Property"
オブジェクト内のプロパティをクラス名で修飾する必要があります。 たとえば、Property="FontSize"
を設定するのではなく、Property を "TextBlock.FontSize"
または "Control.FontSize"
に設定する必要があります。
また、多くの WPF コントロールは、その他の WPF コントロールの組み合わせで構成されていることに注意してください。 型のすべてのコントロールに適用されるスタイルを作成する場合、予期しない結果になる可能性があります。 たとえば、TextBlock 内の Window 型を対象とするスタイルを作成すると、TextBlock
が別のコントロール (TextBlock
など) の一部であったとしても、ウィンドウ内のすべての ListBox コントロールにそのスタイルが適用されます。
関連項目
.NET Desktop feedback