Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

[WPF/xaml]BasedOnを使って元のstyleを受け継ぐ

More than 1 year has passed since last update.

やりたいこと

複数の似たstyleを作るとなったときに、共通する部分だけ1つのstyleにまとめたい。

やり方

BasedOnを使う。

実験コード

下記のようなコードを書いて実験をした。
※Prismを使用しているので、画面はUserControlで作成。

UserControl1.xaml
<UserControl x:Class="PrismSample.Views.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:PrismSample.Views"
             xmlns:prism="http://prismlibrary.com/"
             prism:ViewModelLocator.AutoWireViewModel="True"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <UserControl.Resources>

        <!-- スタイル①:元になるスタイル -->
        <Style x:Key="MyButtonStyle" TargetType="Button">
            <Setter Property="Background" Value="Green"/>
            <Setter Property="Foreground" Value="Yellow"/>
            <Setter Property="BorderBrush" Value="Purple"/>
            <Setter Property="BorderThickness" Value="3"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid>
                            <Ellipse Stroke="{TemplateBinding BorderBrush}" Fill="{TemplateBinding Background}" 
                                     StrokeThickness="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=BorderThickness.Top}"/>
                            <ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <!-- スタイル②:元のスタイルをベースに変更を加えるスタイル -->
        <Style x:Key="MyButtonStyleEx" TargetType="Button" BasedOn="{StaticResource MyButtonStyle}">
            <Setter Property="BorderBrush" Value="Red"/>
            <Setter Property="BorderThickness" Value="20"/>
        </Style>
    </UserControl.Resources>

    <!-- 画面表示メイン -->
    <Grid Background="Beige">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="360"/>
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" Text="画面" FontSize="60"/>
        <Button Grid.Row="1" Content="ボタン" Command="{Binding ButtonCommand}" Style="{DynamicResource MyButtonStyleEx}"/>
    </Grid>
</UserControl>

実験内容

二つのstyleを定義し実験。それぞれ下記のようにしている。

スタイル①:元になるスタイル
ボタン淵色 :紫
ボタン淵太さ:3pixel
ボタン背景 :緑
ボタン文字 :黄色
→このstyle単体で表示させると下記のようになる。

image.png

スタイル②:元のスタイルをベースに変更を加えるスタイル
ボタン淵色 :赤
ボタン淵太さ:20
ボタン背景 :指定なし
ボタン文字 :指定なし
→このstyleで表示させると下記のようになる。

image.png

動作結果

BasedOnを使って元のstyleを受け継ぐと、受け継いだstyle側で指定したプロパティのみ上書きされ、そのほかのプロパティは元のstyleのままになる。

備考

スタイル①:元になるスタイルのほうで、Templateを指定していないと、WPF標準のButtonのstyleを受け継ぐことになる。その場合、マウスOverしたときとか無効になった時の色の変化も受け継がれる。(=Templateを指定すると、まったく何も受け継がなくなり、1から作成になるイメージ)

試しに、スタイル①:元になるスタイル<Setter Property="Template">のTemplate指定部分を丸ごと消すと、下記のようになる。
image.png

Templateで指定していたEllipseなどがなくなり、元のボタンのBorderTHicknessやBorderBrush、Backgroundが指定される形となる。
(マウスオーバー等させると、元のstyle通り、色も変わる)
image.png

参照

Button Class
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.controls.button?view=netframework-4.8

tera1707
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away