【WPF】ボタンのマウスオーバー時の背景色を変更する

# はじめに
前回は動的にGridを表示して、格子内にボタンを配置しました。

https://qiita.com/yaju/items/fd06b0e843ffdeeba7ea

WineskinServerで動作するランチャー作成として参考にしている「[CLaunch](https://forest.watch.impress.co.jp/library/software/claunch/)」を見てみると、背景色はシルバーのグラデーションでマウスオーバー時はゴールドのグラデーションになっています。

まずは真似てみましょう。

# 実装
プログラムは前記事を利用、グリッドの行数は3から2に変更してある。
ボタンはコードを記述して動的に追加している。
今回は出来るだけコードを記述しないで、XAML側で変更していく。

## 背景色を単色に変える
準備として背景色を単色に変えてみます。

```xml
<Window.Resources>
    <Style TargetType="Button">
        <Setter Property="Background" Value="Green" />
    </Style>
</Window.Resources>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/456ee01a-913d-7337-68af-bf608b547356.png)

## 背景色をシルバーのグラデーションに変える
```xml
<Window.Resources>
    <Style TargetType="Button">
        <Setter Property="Background">
            <Setter.Value>
                <LinearGradientBrush  StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="#FFFDFDFD" Offset="0"/>
                    <GradientStop Color="#FFCECECE" Offset="0.35"/>
                    <GradientStop Color="#FFA4A4A4" Offset="0.65"/>
                </LinearGradientBrush>
            </Setter.Value>
         </Setter>
    </Style>
</Window.Resources>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/75413b48-64f5-b07c-ab22-4a7a2440501b.png)

## マウスオーバー時の背景色
同じような方法でマウスオーバー時の背景色を変更してみる。
`Trigger Property="IsMouseOver"`を使用する。

```xml
<Window.Resources>
    <Style TargetType="Button">
        <Setter Property="Background">
            <Setter.Value>
                <LinearGradientBrush  StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="#FFFDFDFD" Offset="0"/>
                    <GradientStop Color="#FFCECECE" Offset="0.35"/>
                    <GradientStop Color="#FFA4A4A4" Offset="0.65"/>
                </LinearGradientBrush>
            </Setter.Value>
         </Setter>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
                <Setter Property="Foreground" Value="red"/>
                <Setter Property="Background" Value="Yellow"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
```
マウスオーバー時に文字色は赤文字になっているが背景色が変わらない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/aaa85b62-b518-418f-9a53-cca2b05df6c7.png)

### テンプレートを使用する
ネットで調べると、`ControlTemplate`を使用する必要があるとのこと。

1.XAMLのデザイナーウィンドウで仮ボタンを配置します。
2.「Buttonオブジェクトを右クリック」->「テンプレートの編集」->「コピーして編集」を選択します。
3.名前(キー)を例 「ButtonStyle2」でOKボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/98be69c7-bfdd-f8aa-dbb6-0faddb582cbc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/330895de-b93c-2033-3471-222d328eb089.png)

`ControlTemplate`で、必要なところ 例`Button.MouseOver.Background`を書き換えます。
その後、StyleのTemplateプロパティの値に`StaticResource ButtonTemplate1`を指定します。
本来は、Pressedした場合なども変更すべきですが、記事として今回はここまでとしておきます。

```xml
<Window.Resources>
    <SolidColorBrush x:Key="Button.MouseOver.Border" Color="#FF3C7FB1"/>
    <SolidColorBrush x:Key="Button.Pressed.Background" Color="#FFC4E5F6"/>
    <SolidColorBrush x:Key="Button.Pressed.Border" Color="#FF2C628B"/>
    <SolidColorBrush x:Key="Button.Disabled.Background" Color="#FFF4F4F4"/>
    <SolidColorBrush x:Key="Button.Disabled.Border" Color="#FFADB2B5"/>
    <SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383"/>
    <LinearGradientBrush x:Key="Button.MouseOver.Background" StartPoint="0,0" EndPoint="0,1">
        <GradientStop Color="#FFFFD030" Offset="0"/>
        <GradientStop Color="#FFFFFDF4" Offset="0.50"/>
        <GradientStop Color="#FFFFD030" Offset="1.00"/>
    </LinearGradientBrush>
    <ControlTemplate x:Key="ButtonTemplate1" TargetType="{x:Type ButtonBase}">
        <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
            <ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="Button.IsDefaulted" Value="true">
                <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="true">
                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.MouseOver.Background}"/>
                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.MouseOver.Border}"/>
            </Trigger>
            <Trigger Property="IsPressed" Value="true">
                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Pressed.Background}"/>
                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Pressed.Border}"/>
            </Trigger>
            <Trigger Property="IsEnabled" Value="false">
                <Setter Property="Background" TargetName="border" Value="{StaticResource Button.Disabled.Background}"/>
                <Setter Property="BorderBrush" TargetName="border" Value="{StaticResource Button.Disabled.Border}"/>
                <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="{StaticResource Button.Disabled.Foreground}"/>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

    <Style TargetType="Button">
        <Setter Property="Template" Value="{StaticResource ButtonTemplate1}" />
        <Setter Property="Background">
            <Setter.Value>
                <LinearGradientBrush  StartPoint="0,0" EndPoint="1,1">
                    <GradientStop Color="#FFFDFDFD" Offset="0"/>
                    <GradientStop Color="#FFCECECE" Offset="0.35"/>
                    <GradientStop Color="#FFA4A4A4" Offset="0.65"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
                <Setter Property="Foreground" Value="red"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14053/aa4edbc0-4266-e38d-e82f-ca7f2bf80850.png)

## スタイルに名前を付ける
このままだと全てのボタンでこのスタイル採用されてしまうので、スタイルに名前を付けます。

```xml
<Style x:Key="ButtonStyle1" TargetType="Button" >
```

Styleプロパティに`Resources["ButtonStyle1"]`を割り当てます。
これで変更したいボタンのみスタイルが変更されます。

```cs
Button MyControl = new Button();
MyControl.Content = count.ToString();
MyControl.Name = "Button" + count.ToString();
MyControl.Click += new RoutedEventHandler(Button_Click);
MyControl.Style = (Style)Resources["ButtonStyle1"];
```

# 最後に
XAMLは癖がありますが、分かってしまえばレイアウトの自由度は高いです。
次回は、ランチャーなのでボタンにアイコンイメージを付けてみます。その上でスタイルの外部ファイル化も一緒にやってしまいます。また、CustomControl化にするかも知れません。

# 参照
* [画面のほとんどを XAML を記述せずに作成してみた](https://tnakamura.hatenablog.com/entry/20081006/1225070010)
* [How do you change Background for a Button MouseOver in WPF? - Stack Overflow](https://stackoverflow.com/questions/17259280/how-do-you-change-background-for-a-button-mouseover-in-wpf)
* [[WPF] マウスオーバー時のボタンのボーダーと背景色をデフォルトから変更する](http://gootara.org/library/2016/07/wpf-hvr.html)
* [[WPF] xaml画面の構成要素の見た目のいじりかた(Style/Templateの使いどき)あれこれ](https://qiita.com/tera1707/items/4a2acd893f6098737987)