この記事では、WPFでアイコンを表示したいときに使えるアイコンボタンを作成していきます。
この記事で作成するもの

上記のアイコンボタンを作成します。色を自由に変更することも可能です。
IconButtonコントロールの作成
まず初めにButtonを拡張したIconButtonコントロールを作成します。
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace NumericUpDown.Controls;
public class IconButton : Button
{
private static readonly PathGeometry DefaultIcon = new();
/// <summary>Identifies the <see cref="Icon"/> dependency property.</summary>
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
nameof(Icon),
typeof(PathGeometry),
typeof(IconButton),
new PropertyMetadata(DefaultIcon));
/// <summary>Identifies the <see cref="IconWidth"/> dependency property.</summary>
public static readonly DependencyProperty IconWidthProperty = DependencyProperty.Register(
nameof(IconWidth),
typeof(double),
typeof(IconButton));
/// <summary>Identifies the <see cref="IconHeight"/> dependency property.</summary>
public static readonly DependencyProperty IconHeightProperty = DependencyProperty.Register(
nameof(IconHeight),
typeof(double),
typeof(IconButton));
static IconButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(IconButton), new FrameworkPropertyMetadata(typeof(IconButton)));
}
/// <summary>
/// Specify the icon data to be displayed on the button.
/// </summary>
public PathGeometry Icon
{
get => (PathGeometry)this.GetValue(IconProperty);
set => this.SetValue(IconProperty, value);
}
/// <summary>
/// Specify the width of the icon.
/// </summary>
public double IconWidth
{
get => (double)this.GetValue(IconWidthProperty);
set => this.SetValue(IconWidthProperty, value);
}
/// <summary>
/// Specify the height of the icon.
/// </summary>
public double IconHeight
{
get => (double)this.GetValue(IconHeightProperty);
set => this.SetValue(IconHeightProperty, value);
}
}
IconButtonのスタイル定義
スタイルの作成と適用方法の詳しい解説はこちらの記事を参照ください。ここではIconButtonのスタイルを変更してモダンなスタイルを作っていきます。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:NumericUpDown.Controls">
<Style x:Key="FocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="0" StrokeDashArray="1 2" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" SnapsToDevicePixels="true" StrokeThickness="1"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="Button.Static.Background" Color="Transparent"/>
<Style TargetType="{x:Type ctrl:IconButton}">
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Background" Value="{StaticResource Button.Static.Background}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="IconWidth" Value="18"/>
<Setter Property="IconHeight" Value="18"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Viewbox
Width="{Binding IconWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ctrl:IconButton}}"
Height="{Binding IconHeight, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ctrl:IconButton}}"
Stretch="Uniform"
StretchDirection="Both">
<Path
Fill="{TemplateBinding TextElement.Foreground}"
Data="{Binding Icon, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ctrl:IconButton}}"/>
</Viewbox>
<ContentPresenter
x:Name="contentPresenter"
Focusable="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" Value="0.56"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
IconButtonの使い方
作成したIconButtonをxamlで使用します。使用方法は下記の通りです。
<ctrl:IconButton
Icon="{StaticResource icon-search}"
Foreground="#FF673ab7"/>
ここでctrlはIconButtonがあるnamespaceです。
注意点
- App.xamlの辞書に、定義したIconButtonのスタイルファイルを登録し忘れないようにする(詳細についてはこちらの記事を参照)
- アイコンの色はForegroundプロパティを変更することで変えることが可能です。