No more Death March

あるSEのチラシの裏 C# WPF

WPF ボタンのカスタマイズ方法概略

はじめに

入力に使うコントロールは結構癖があり忘れやすいのでメモしておきます。

仕事で使う場合だと色を変えたいとかアイコン埋め込みたいとか、
色々あるかと思いますがあくまで雰囲気重視の記述です。

ボタン側のXAML

ボタンのXAML、Buttonクラスを継承して記述、コードビハインドは無し。
VSでユーザーコントロールWPF)を追加して派生元をUserControlからButtonに変更したものを編集

<Button x:Class="WpfApp1.CustomButton"
             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:WpfApp1"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800"
             OverridesDefaultStyle="True"
             FocusVisualStyle="{x:Null}"
             >
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Grid>
                <Border
                    x:Name="ButtonVisual"
                    BorderBrush="DimGray"
                    BorderThickness="2"
                    Background="AliceBlue"
                    >
                    <ContentPresenter
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Content="{TemplateBinding Content}"
                        />
                </Border>
                <Border
                    x:Name="MaskOnPressed"
                    Background="Black"
                    Opacity="0.1"
                    Visibility="Hidden"
                    />
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsFocused" Value="true">
                    <Setter TargetName="ButtonVisual" Property="BorderBrush" Value="MidnightBlue"/>
                </Trigger>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter TargetName="ButtonVisual" Property="Background" Value="Lavender"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Opacity" Value="0.5"/>
                </Trigger>
                <Trigger Property="IsPressed" Value="true">
                    <Setter TargetName="MaskOnPressed" Property="Visibility" Value="Visible"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Button.Template>
</Button>

画面側のXAML

ボタンを画面に貼っつけたXAML、こちらもコードビハインドなし。

<Window x:Class="WpfApp1.MainWindow"
        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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Canvas>
        <local:CustomButton
            Canvas.Left="10"
            Canvas.Top="10"
            Width="100"
            Height="20"
            Content="ボタン1"
            />
        <local:CustomButton
            Canvas.Left="10"
            Canvas.Top="40"
            Width="100"
            Height="20"
            Content="ボタン2"
            />
        <local:CustomButton
            Canvas.Left="10"
            Canvas.Top="70"
            Width="100"
            Height="20"
            Content="ボタン3"
            IsEnabled="False"
            />
    </Canvas>
</Window>

実行時イメージ

上から順に、
フォーカス取得中
フォーカス無しの表示
Disable(IsEnabled=false)の表示

f:id:nomoredeathmarch:20180522231245p:plain

ポイント

標準スタイルの無効化

・OverridesDefaultStyle=”true”で標準のスタイルを読み込まないように
・FocusVisualStyle="{x:Null}"でフォーカス取得時スタイルを初期化
 (フォーカス取得時に点線が表示されるやつ。)

トリガーで実現しているもの

・フォーカス時に外枠の色を濃い目に変更
・マウスオーバー時に塗りつぶし色を濃い目に変更
・Disableの時、全体を半透明にして使えないっぽい外観に
・押下時、半透明のフィルタを被せて操作に対するレスポンスを表現