C#トグルボタンの作り方|WinForms・WPF別に実装方法と状態切り替えを解説

はじめに

C#で画面アプリを作っていると、「クリックするたびにON/OFFを切り替えたい」「押された状態を保持するボタンを作りたい」という場面があります。このような用途で使うのがトグルボタンです。

トグルボタンは、通常のボタンのように一度押して処理を実行するだけでなく、押すたびに状態を切り替えられるUI部品です。たとえば、ミュートのON/OFF、設定の有効・無効、表示モードの切り替え、ツールバーの選択状態などに利用できます。

C#でトグルボタンを作る方法は、WinFormsとWPFで異なります。WinFormsでは主にCheckBoxをボタン風に表示する方法や、Buttonを使って疑似的にトグル動作を実装する方法があります。一方、WPFでは標準でToggleButtonコントロールが用意されているため、より自然にON/OFF状態を扱えます。

この記事では、C#のトグルボタンについて、WinFormsとWPFそれぞれの作り方、状態管理、見た目のカスタマイズ、MVVMでの実装、よくあるエラーと対処法まで詳しく解説します。

1. C#のトグルボタンとは?できることと使いどころ

1-1. トグルボタンはON/OFFの状態を切り替えるボタン

トグルボタンとは、クリックするたびにONとOFFの状態を切り替えるボタンのことです。

通常のButtonは、クリックされた瞬間に処理を実行するだけで、押された状態を保持しません。一方、トグルボタンは「現在ONなのかOFFなのか」という状態を持ちます。

たとえば、次のような動作です。

C#
OFFの状態でクリック  ONになる
ONの状態でクリック OFFになる

このように、ユーザーの操作によって状態を保持しながら切り替えるUIを作りたい場合に、トグルボタンが便利です。

C#では、WinFormsとWPFでトグルボタンの実装方法が異なります。WinFormsではCheckBoxやButtonを使って実装することが多く、WPFではToggleButtonコントロールを使うのが基本です。

1-2. 通常のButton・CheckBox・RadioButtonとの違い

トグルボタンを理解するには、Button、CheckBox、RadioButtonとの違いを押さえておくと分かりやすくなります。

Buttonは、クリックされたときに処理を実行するためのコントロールです。クリック後に状態を保持しないため、ON/OFFの切り替えにはそのままでは向いていません。

CheckBoxは、チェックあり・チェックなしの状態を持つコントロールです。ON/OFF状態を扱えるため、WinFormsではCheckBoxをボタン風に表示してトグルボタンとして使う方法がよく使われます。

RadioButtonは、複数の選択肢の中から1つだけを選ばせるためのコントロールです。複数のトグルボタンのうち1つだけを選択状態にしたい場合は、RadioButtonをボタン風に見せる方法もあります。

WPFのToggleButtonは、ON/OFF状態を持つボタン専用のコントロールです。IsCheckedプロパティを使って状態を取得・設定でき、見た目のカスタマイズもしやすいのが特徴です。

1-3. WinFormsとWPFで実装方法が異なる理由

WinFormsとWPFでは、UIの設計思想が異なります。

WinFormsは、コントロールをフォーム上に配置し、イベントに処理を書くスタイルが基本です。標準コントロールとして「ToggleButton」という名前のコントロールは用意されていないため、CheckBoxやButtonを使ってトグルボタンを実装します。

一方、WPFにはToggleButtonコントロールが用意されています。WPFではXAMLでUIを定義し、Style、Trigger、Binding、ControlTemplateなどを使って見た目や動作を柔軟に制御できます。そのため、トグルボタンを標準機能として扱いやすくなっています。

つまり、C#でトグルボタンを作る場合、WinFormsでは既存コントロールを工夫して実装し、WPFではToggleButtonを使って実装するのが基本です。

1-4. トグルボタンが使われる代表例

トグルボタンは、ON/OFFや選択状態を切り替える場面でよく使われます。

代表的な例は次のとおりです。

・ミュートのON/OFF
・ダークモードのON/OFF
・編集モードと閲覧モードの切り替え
・検索条件の有効・無効
・ツールバーの太字、斜体、下線の選択状態
・表示/非表示の切り替え
・自動保存の有効/無効
・スイッチ風の設定画面

ユーザーに現在の状態を分かりやすく見せたい場合は、トグルボタンの見た目をON/OFFで変更すると効果的です。たとえば、ONなら背景色を青や緑にし、OFFならグレーにすることで、状態が直感的に伝わります。

2. C#でトグルボタンを作る前に押さえる基本

2-1. 状態管理はboolまたはIsCheckedで行う

トグルボタンの実装で重要なのは、現在の状態をどこで管理するかです。

WinFormsでButtonを使って疑似トグルボタンを作る場合は、bool型の変数を用意してON/OFFを管理します。

C#
private bool isOn = false;

クリックされたら、次のように値を反転させます。

C#
isOn = !isOn;

CheckBoxを使う場合は、Checkedプロパティで状態を取得できます。

C#
bool isOn = checkBox1.Checked;

WPFのToggleButtonでは、IsCheckedプロパティを使います。

C#
bool isOn = toggleButton1.IsChecked == true;

WPFのIsCheckedはbool?型、つまりnullable boolです。そのため、true、false、nullの3状態を取る可能性があります。通常のON/OFFだけで使う場合は、IsChecked == true のように判定すると安全です。

2-2. ON/OFFで表示テキストを切り替える考え方

トグルボタンでは、状態に応じて表示テキストを切り替えると分かりやすくなります。

たとえば、ONのときは「ON」、OFFのときは「OFF」と表示します。

WinFormsでは、Textプロパティを変更します。

C#
checkBox1.Text = checkBox1.Checked ? "ON" : "OFF";

WPFでは、Contentプロパティを変更します。

C#
toggleButton1.Content = toggleButton1.IsChecked == true ? "ON" : "OFF";

処理自体はシンプルですが、状態変更のたびに表示を更新することが重要です。クリックイベントだけでなく、状態変更イベントに処理を書くと、プログラム側から状態を変更した場合にも表示が同期しやすくなります。

2-3. ON/OFFで背景色や見た目を切り替える考え方

トグルボタンは、文字だけでなく背景色や文字色を切り替えることで、現在の状態をより分かりやすくできます。

WinFormsではBackColorやForeColorを使います。

C#
checkBox1.BackColor = checkBox1.Checked ? Color.LightGreen : Color.LightGray;
checkBox1.ForeColor = Color.Black;

WPFでは、コードビハインドでBackgroundを変更する方法もありますが、StyleやTriggerを使う方法が一般的です。

XML
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="LightGreen"/>
</Trigger>

WPFでは見た目の変更をXAML側に分けることで、処理ロジックとデザインを分離しやすくなります。

2-4. クリックイベントと状態変更イベントの使い分け

トグルボタンを実装するときは、クリックイベントと状態変更イベントの違いを理解しておく必要があります。

クリックイベントは、ユーザーがクリックしたときに発生します。たとえばWinFormsのButton.Clickや、WPFのButton.Clickが該当します。

一方、状態変更イベントは、ON/OFFの状態が変わったときに発生します。WinFormsのCheckBox.CheckedChangedや、WPFのToggleButton.Checked、Uncheckedなどが該当します。

トグルボタンの表示を更新する処理は、クリックイベントよりも状態変更イベントに書く方が扱いやすいです。なぜなら、ユーザー操作だけでなく、コードから状態を変更した場合にも同じ処理を実行できるからです。

たとえば、WinFormsでは次のように書きます。

C#
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
UpdateToggleButton();
}

状態を変更する処理と、表示を更新する処理を分けておくと、コードの見通しも良くなります。

3. WinFormsでトグルボタンを作る方法

3-1. CheckBoxをトグルボタン風にする基本実装

WinFormsでトグルボタンを作る代表的な方法は、CheckBoxを使う方法です。

CheckBoxはもともとCheckedプロパティを持っているため、ON/OFF状態の管理に向いています。ただし、標準の見た目はチェックボックスなので、ボタンのように表示したい場合はAppearanceプロパティを変更します。

まず、フォームにCheckBoxを配置します。名前は例としてcheckBoxToggleにします。

C#
private void checkBoxToggle_CheckedChanged(object sender, EventArgs e)
{
if (checkBoxToggle.Checked)
{
checkBoxToggle.Text = "ON";
}
else
{
checkBoxToggle.Text = "OFF";
}
}

このコードでは、CheckBoxのチェック状態に応じて表示テキストを切り替えています。

3-2. AppearanceをButtonに設定してボタン表示にする

CheckBoxをボタン風に表示するには、AppearanceプロパティにAppearance.Buttonを設定します。

C#
checkBoxToggle.Appearance = Appearance.Button;

フォームのLoadイベントなどで設定すると、アプリ起動時からボタンの見た目になります。

C#
private void Form1_Load(object sender, EventArgs e)
{
checkBoxToggle.Appearance = Appearance.Button;
checkBoxToggle.TextAlign = ContentAlignment.MiddleCenter;
checkBoxToggle.Text = "OFF";
}

これにより、CheckBoxでありながら、見た目はボタンのようになります。クリックするたびにCheckedが切り替わるため、簡単にトグルボタンを実装できます。

3-3. CheckedプロパティでON/OFF状態を取得する

WinFormsのCheckBoxでは、CheckedプロパティでON/OFF状態を取得します。

C#
if (checkBoxToggle.Checked)
{
MessageBox.Show("現在はONです");
}
else
{
MessageBox.Show("現在はOFFです");
}

CheckedがtrueならON、falseならOFFとして扱えます。

また、コードから状態を変更することもできます。

C#
checkBoxToggle.Checked = true;  // ONにする
checkBoxToggle.Checked = false; // OFFにする

Checkedプロパティを変更すると、通常はCheckedChangedイベントも発生します。そのため、表示更新処理をCheckedChangedイベントにまとめておくと便利です。

3-4. CheckedChangedイベントで状態切り替え処理を書く

CheckBoxを使ったトグルボタンでは、CheckedChangedイベントに状態変更時の処理を書くのが基本です。

C#
private void checkBoxToggle_CheckedChanged(object sender, EventArgs e)
{
if (checkBoxToggle.Checked)
{
checkBoxToggle.Text = "ON";
checkBoxToggle.BackColor = Color.LightGreen;
}
else
{
checkBoxToggle.Text = "OFF";
checkBoxToggle.BackColor = Color.LightGray;
}
}

このように、CheckedChangedイベントでTextやBackColorを変更すると、ON/OFFの状態が見た目に反映されます。

3-5. ON/OFFに応じてTextやBackColorを変更する

表示更新処理は、メソッドとして分けておくと再利用しやすくなります。

C#
private void UpdateToggleView()
{
if (checkBoxToggle.Checked)
{
checkBoxToggle.Text = "ON";
checkBoxToggle.BackColor = Color.LightGreen;
checkBoxToggle.ForeColor = Color.Black;
}
else
{
checkBoxToggle.Text = "OFF";
checkBoxToggle.BackColor = Color.LightGray;
checkBoxToggle.ForeColor = Color.Black;
}
}

CheckedChangedイベントから呼び出します。

C#
private void checkBoxToggle_CheckedChanged(object sender, EventArgs e)
{
UpdateToggleView();
}

フォーム読み込み時にも呼び出すと、初期表示も整えられます。

C#
private void Form1_Load(object sender, EventArgs e)
{
checkBoxToggle.Appearance = Appearance.Button;
checkBoxToggle.TextAlign = ContentAlignment.MiddleCenter;
UpdateToggleView();
}

このようにすると、初期状態とクリック後の表示が常に一致します。

3-6. Buttonコントロールで疑似トグルボタンを作る方法

WinFormsでは、通常のButtonを使って疑似的なトグルボタンを作ることもできます。

ButtonにはCheckedプロパティがないため、bool型の変数で状態を管理します。

C#
private bool isToggleOn = false;

private void buttonToggle_Click(object sender, EventArgs e)
{
isToggleOn = !isToggleOn;
UpdateButtonToggleView();
}

private void UpdateButtonToggleView()
{
if (isToggleOn)
{
buttonToggle.Text = "ON";
buttonToggle.BackColor = Color.LightGreen;
}
else
{
buttonToggle.Text = "OFF";
buttonToggle.BackColor = Color.LightGray;
}
}

Buttonを使う方法はシンプルですが、状態管理を自分で実装する必要があります。ON/OFF状態を標準プロパティで扱いたい場合は、CheckBoxをボタン風にする方法の方が簡単です。

3-7. ToolStripButtonでトグル動作を実装する方法

ツールバー上でトグルボタンを使いたい場合は、ToolStripButtonを使います。

ToolStripButtonにはCheckedプロパティがあり、CheckOnClickをtrueにすると、クリックするたびにCheckedが切り替わります。

C#
private void Form1_Load(object sender, EventArgs e)
{
toolStripButton1.CheckOnClick = true;
toolStripButton1.Text = "OFF";
}

private void toolStripButton1_CheckedChanged(object sender, EventArgs e)
{
if (toolStripButton1.Checked)
{
toolStripButton1.Text = "ON";
}
else
{
toolStripButton1.Text = "OFF";
}
}

ツールバーの表示切り替え、編集モードのON/OFF、フィルターの有効・無効などに便利です。

4. WPFでToggleButtonを作る方法

4-1. WPFではToggleButtonコントロールを使う

WPFでトグルボタンを作る場合は、ToggleButtonコントロールを使うのが基本です。

ToggleButtonは、System.Windows.Controls.Primitives名前空間に含まれるコントロールで、IsCheckedプロパティによってON/OFF状態を管理します。

通常のButtonと違い、クリック後も押された状態を保持できます。そのため、C# WPFでトグルボタンを作りたい場合は、まずToggleButtonを使うと考えるとよいでしょう。

4-2. XAMLでToggleButtonを配置する基本コード

WPFでToggleButtonを配置する基本コードは次のとおりです。

XML
<Window x:Class="ToggleButtonSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ToggleButton Sample"
Height="200"
Width="300">
<Grid>
<ToggleButton x:Name="toggleButton"
Width="120"
Height="40"
Content="OFF"
Checked="toggleButton_Checked"
Unchecked="toggleButton_Unchecked"/>
</Grid>
</Window>

ToggleButtonをクリックすると、CheckedまたはUncheckedイベントが発生します。ONになったときはChecked、OFFになったときはUncheckedです。

4-3. IsCheckedプロパティでON/OFF状態を取得する

WPFのToggleButtonでは、IsCheckedプロパティで状態を取得します。

C#
if (toggleButton.IsChecked == true)
{
MessageBox.Show("現在はONです");
}
else
{
MessageBox.Show("現在はOFFです");
}

IsCheckedはbool?型です。通常の2状態で使う場合も、toggleButton.IsChecked == true のように比較すると安全です。

コードから状態を変更することもできます。

C#
toggleButton.IsChecked = true;  // ON
toggleButton.IsChecked = false; // OFF

4-4. Checked・Uncheckedイベントで状態切り替え処理を書く

WPFでは、CheckedイベントとUncheckedイベントを使って、ON/OFFの処理を分けられます。

C#
private void toggleButton_Checked(object sender, RoutedEventArgs e)
{
toggleButton.Content = "ON";
}

private void toggleButton_Unchecked(object sender, RoutedEventArgs e)
{
toggleButton.Content = "OFF";
}

背景色も変更したい場合は、次のように書けます。

C#
private void toggleButton_Checked(object sender, RoutedEventArgs e)
{
toggleButton.Content = "ON";
toggleButton.Background = Brushes.LightGreen;
}

private void toggleButton_Unchecked(object sender, RoutedEventArgs e)
{
toggleButton.Content = "OFF";
toggleButton.Background = Brushes.LightGray;
}

ただし、WPFでは見た目の変更はXAMLのStyleやTriggerで行う方が管理しやすくなります。

4-5. IsThreeStateで3状態のトグルボタンを作る

WPFのToggleButtonは、IsThreeStateをtrueにすると3状態を扱えます。

XML
<ToggleButton x:Name="toggleButton"
Width="120"
Height="40"
Content="状態切替"
IsThreeState="True"/>

3状態では、IsCheckedが次のいずれかになります。

true  → ON
false → OFF
null → 未確定・中間状態

C#側では次のように判定します。

C#
if (toggleButton.IsChecked == true)
{
toggleButton.Content = "ON";
}
else if (toggleButton.IsChecked == false)
{
toggleButton.Content = "OFF";
}
else
{
toggleButton.Content = "未設定";
}

通常のON/OFFボタンではIsThreeStateを使う必要はありません。nullが不要な場合は、IsThreeStateをfalseのまま使いましょう。

4-6. Contentを使ってON/OFFの表示を切り替える

WPFのToggleButtonでは、表示内容をContentプロパティで指定します。

XML
<ToggleButton x:Name="toggleButton"
Width="120"
Height="40"
Content="OFF"/>

コードから切り替える場合は、次のようにします。

C#
private void toggleButton_Checked(object sender, RoutedEventArgs e)
{
toggleButton.Content = "ON";
}

private void toggleButton_Unchecked(object sender, RoutedEventArgs e)
{
toggleButton.Content = "OFF";
}

MVVMで実装する場合は、ContentをViewModelのプロパティにバインドする方法もあります。画面の状態とデータを分離したい場合は、バインディングを使うのがおすすめです。

4-7. Visual StudioのツールボックスにToggleButtonがない場合の対処

Visual StudioのツールボックスにToggleButtonが表示されない場合があります。その場合でも、XAMLに直接記述すれば使用できます。

XML
<ToggleButton Content="OFF"
Width="120"
Height="40"/>

ToggleButtonは、WPFで利用できる標準コントロールです。ツールボックスに見つからない場合は、検索ボックスで「ToggleButton」と入力するか、XAMLに直接書いて配置しましょう。

また、必要に応じて次の名前空間を確認します。

C#
using System.Windows.Controls.Primitives;

コードビハインドでToggleButton型を扱う場合に必要になることがあります。

5. WPFのトグルボタンを見やすくカスタマイズする方法

5-1. Styleで背景色・文字色・サイズを変更する

WPFでは、Styleを使ってToggleButtonの見た目をまとめて設定できます。

XML
<ToggleButton Content="OFF"
Width="120"
Height="40"
FontSize="16"
Background="LightGray"
Foreground="Black"/>

複数のToggleButtonに同じデザインを適用したい場合は、Window.ResourcesなどにStyleを定義します。

XML
<Window.Resources>
<Style x:Key="ToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="40"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="Black"/>
</Style>
</Window.Resources>

使用するときは、Styleプロパティで指定します。

XML
<ToggleButton Content="OFF"
Style="{StaticResource ToggleButtonStyle}"/>

Styleを使うことで、デザインを一か所で管理できます。

5-2. TriggerでON/OFF時の見た目を切り替える

WPFのToggleButtonでは、Triggerを使ってIsCheckedの値に応じて見た目を変更できます。

XML
<Style x:Key="ToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Content" Value="OFF"/>
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="Black"/>

<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="ON"/>
<Setter Property="Background" Value="LightGreen"/>
</Trigger>
</Style.Triggers>
</Style>

このStyleを適用すると、OFFのときはContentが「OFF」、ONのときは「ON」になり、背景色も切り替わります。

XML
<ToggleButton Style="{StaticResource ToggleButtonStyle}"/>

コードビハインドで見た目を変更しなくてよいため、WPFらしい実装になります。

5-3. ControlTemplateでスイッチ風デザインにする

ToggleButtonをスイッチ風にしたい場合は、ControlTemplateを使います。

XML
<Style x:Key="SwitchToggleStyle" TargetType="ToggleButton">
<Setter Property="Width" Value="70"/>
<Setter Property="Height" Value="30"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border x:Name="SwitchBackground"
CornerRadius="15"
Background="LightGray">
<Grid>
<Ellipse x:Name="SwitchKnob"
Width="26"
Height="26"
Fill="White"
HorizontalAlignment="Left"
Margin="2"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="SwitchBackground"
Property="Background"
Value="LightGreen"/>
<Setter TargetName="SwitchKnob"
Property="HorizontalAlignment"
Value="Right"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

使用例は次のとおりです。

XML
<ToggleButton Style="{StaticResource SwitchToggleStyle}"/>

ControlTemplateを使うと、標準のボタンらしい見た目を完全に置き換えられます。設定画面などでよくあるスイッチ型UIを作りたい場合に便利です。

5-4. 画像やアイコン付きトグルボタンを作る

ToggleButtonのContentには、文字だけでなくStackPanelやImageなども配置できます。

XML
<ToggleButton Width="140" Height="50">
<StackPanel Orientation="Horizontal">
<TextBlock Text="🔊" FontSize="18" Margin="0,0,8,0"/>
<TextBlock Text="Sound"/>
</StackPanel>
</ToggleButton>

画像を使う場合は、ImageコントロールをContent内に配置します。

XML
<ToggleButton Width="140" Height="50">
<StackPanel Orientation="Horizontal">
<Image Source="icon.png"
Width="24"
Height="24"
Margin="0,0,8,0"/>
<TextBlock Text="通知"/>
</StackPanel>
</ToggleButton>

ON/OFFでアイコンを切り替えたい場合は、StyleのTriggerやDataTriggerを使うと管理しやすくなります。

5-5. 複数のトグルボタンを横並びにする

複数のToggleButtonを横並びにするには、StackPanelを使います。

XML
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<ToggleButton Content="A" Width="80" Height="40" Margin="5"/>
<ToggleButton Content="B" Width="80" Height="40" Margin="5"/>
<ToggleButton Content="C" Width="80" Height="40" Margin="5"/>
</StackPanel>

それぞれ独立したON/OFF状態を持たせたい場合は、ToggleButtonを複数配置すれば問題ありません。

一方、複数のうち1つだけを選択状態にしたい場合は、ToggleButtonよりもRadioButtonを使う方が向いています。

5-6. RadioButtonをトグルボタン風に表示する方法

複数の選択肢のうち1つだけを選ばせたい場合は、RadioButtonをボタン風に表示できます。

XML
<StackPanel Orientation="Horizontal">
<RadioButton Content="左"
GroupName="AlignGroup"
Style="{StaticResource {x:Type ToggleButton}}"/>
<RadioButton Content="中央"
GroupName="AlignGroup"
Style="{StaticResource {x:Type ToggleButton}}"/>
<RadioButton Content="右"
GroupName="AlignGroup"
Style="{StaticResource {x:Type ToggleButton}}"/>
</StackPanel>

環境やテーマによってはこの書き方が期待通りに表示されない場合もあるため、確実にボタン風にしたい場合はRadioButton用のStyleを定義します。

RadioButtonはGroupNameが同じもの同士で排他的に選択されるため、「複数のうち1つだけ選択」というUIに適しています。

6. MVVMでWPFのトグルボタンを実装する方法

6-1. IsCheckedをViewModelのboolプロパティにバインドする

WPFでMVVMを使う場合は、ToggleButtonのIsCheckedをViewModelのboolプロパティにバインドします。

XAMLは次のようになります。

XML
<ToggleButton Content="切り替え"
Width="120"
Height="40"
IsChecked="{Binding IsEnabledOption, Mode=TwoWay}"/>

ViewModel側には、bool型のプロパティを用意します。

C#
private bool _isEnabledOption;

public bool IsEnabledOption
{
get => _isEnabledOption;
set
{
if (_isEnabledOption != value)
{
_isEnabledOption = value;
OnPropertyChanged(nameof(IsEnabledOption));
}
}
}

このようにすると、ToggleButtonのON/OFF状態とViewModelの値が同期します。

6-2. TwoWayバインディングで状態を同期する

ToggleButtonのIsCheckedは、画面からViewModelへ値を渡すだけでなく、ViewModelから画面へも反映する必要があります。

そのため、ModeにはTwoWayを指定します。

XML
IsChecked="{Binding IsEnabledOption, Mode=TwoWay}"

TwoWayバインディングにより、ユーザーがToggleButtonをクリックしたときはViewModelの値が更新され、ViewModel側で値を変更したときは画面のToggleButtonも更新されます。

6-3. INotifyPropertyChangedで画面表示を更新する

ViewModelの値が変わったときに画面へ通知するには、INotifyPropertyChangedを実装します。

C#
using System.ComponentModel;
using System.Runtime.CompilerServices;

public class MainViewModel : INotifyPropertyChanged
{
private bool _isEnabledOption;

public bool IsEnabledOption
{
get => _isEnabledOption;
set
{
if (_isEnabledOption != value)
{
_isEnabledOption = value;
OnPropertyChanged();
OnPropertyChanged(nameof(ToggleText));
}
}
}

public string ToggleText => IsEnabledOption ? "ON" : "OFF";

public event PropertyChangedEventHandler? PropertyChanged;

protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

ここでは、IsEnabledOptionが変わったときにToggleTextも更新されるように通知しています。

6-4. Commandでクリック処理を分離する

MVVMでは、クリック時の処理をコードビハインドに書くのではなく、CommandとしてViewModelに分離することが多いです。

XAMLではCommandをバインドします。

XML
<ToggleButton Content="{Binding ToggleText}"
IsChecked="{Binding IsEnabledOption, Mode=TwoWay}"
Command="{Binding ToggleCommand}"
Width="120"
Height="40"/>

ViewModel側ではICommandを実装したコマンドを用意します。

C#
using System;
using System.Windows.Input;

public class RelayCommand : ICommand
{
private readonly Action _execute;

public RelayCommand(Action execute)
{
_execute = execute;
}

public event EventHandler? CanExecuteChanged;

public bool CanExecute(object? parameter)
{
return true;
}

public void Execute(object? parameter)
{
_execute();
}
}

ViewModelでCommandを定義します。

C#
public ICommand ToggleCommand { get; }

public MainViewModel()
{
ToggleCommand = new RelayCommand(OnToggle);
}

private void OnToggle()
{
// トグル時に実行したい処理を書く
}

IsCheckedの切り替え自体はバインディングで行い、追加処理だけをCommandに書くと整理しやすくなります。

6-5. MVVMでTextやContentを切り替える実装例

MVVMでON/OFFの表示を切り替える場合は、ContentをViewModelのプロパティにバインドします。

XML
<ToggleButton Content="{Binding ToggleText}"
IsChecked="{Binding IsEnabledOption, Mode=TwoWay}"
Width="120"
Height="40"/>

ViewModel側では、状態に応じて文字列を返します。

C#
public string ToggleText => IsEnabledOption ? "ON" : "OFF";

IsEnabledOptionが変更されたときにToggleTextの変更通知も出すことがポイントです。

C#
set
{
if (_isEnabledOption != value)
{
_isEnabledOption = value;
OnPropertyChanged(nameof(IsEnabledOption));
OnPropertyChanged(nameof(ToggleText));
}
}

これにより、ユーザーがToggleButtonをクリックすると、IsEnabledOptionが変わり、同時にContentの表示もON/OFFに更新されます。

7. C#トグルボタン実装でよくあるエラーと対処法

7-1. クリックしても状態が変わらない

クリックしても状態が変わらない場合は、使用しているコントロールを確認しましょう。

WinFormsのButtonにはCheckedプロパティがありません。そのため、Buttonを使っている場合は、bool変数で状態を反転させる必要があります。

C#
isToggleOn = !isToggleOn;

WinFormsでCheckBoxを使っている場合は、CheckedChangedイベントが正しく関連付けられているか確認します。

WPFのToggleButtonで状態が変わらない場合は、IsEnabledがfalseになっていないか、StyleやTemplateで操作を妨げていないか確認してください。

7-2. ON/OFFの表示テキストが更新されない

表示テキストが更新されない場合は、状態変更時にTextまたはContentを変更しているか確認します。

WinFormsではTextを変更します。

C#
checkBoxToggle.Text = checkBoxToggle.Checked ? "ON" : "OFF";

WPFではContentを変更します。

C#
toggleButton.Content = toggleButton.IsChecked == true ? "ON" : "OFF";

MVVMの場合は、ContentにバインドしているプロパティのPropertyChanged通知が不足している可能性があります。状態プロパティだけでなく、表示用プロパティにも通知を出しましょう。

C#
OnPropertyChanged(nameof(ToggleText));

7-3. WPFでIsCheckedがnullになる

WPFのToggleButtonのIsCheckedはbool?型です。IsThreeStateがtrueの場合、true、false、nullの3状態を取ります。

nullが不要な場合は、IsThreeStateを設定しないか、falseにします。

XML
<ToggleButton IsThreeState="False"/>

C#側で判定するときは、次のように書くと安全です。

C#
if (toggleButton.IsChecked == true)
{
// ON
}
else
{
// OFFまたはnull
}

bool型に直接代入しようとしてエラーになる場合は、null対策を行います。

C#
bool isOn = toggleButton.IsChecked ?? false;

7-4. デザイン変更が反映されない

WPFでデザイン変更が反映されない場合は、StyleやControlTemplateの設定を確認します。

特にControlTemplateを定義している場合、Backgroundなどのプロパティを設定しても、テンプレート内で使われていなければ見た目に反映されません。

たとえば、Template内のBorderにBackgroundを反映させたい場合は、TemplateBindingを使います。

XML
<Border Background="{TemplateBinding Background}">

また、Styleのキーを定義しただけで、ToggleButtonに適用していないケースもあります。

XML
<ToggleButton Style="{StaticResource ToggleButtonStyle}"/>

Styleを定義したら、対象のコントロールに適用されているか確認しましょう。

7-5. 複数ボタンのうち1つだけ選択状態にしたい

複数のボタンのうち1つだけを選択状態にしたい場合、ToggleButtonを複数配置するだけでは不十分です。ToggleButtonはそれぞれ独立してON/OFF状態を持つため、複数同時にONになる可能性があります。

排他的に選択したい場合は、RadioButtonを使うのが簡単です。

XML
<StackPanel Orientation="Horizontal">
<RadioButton Content="A" GroupName="Group1"/>
<RadioButton Content="B" GroupName="Group1"/>
<RadioButton Content="C" GroupName="Group1"/>
</StackPanel>

見た目をトグルボタン風にしたい場合は、RadioButtonにStyleを設定してボタン風にします。

WinFormsの場合も、排他的な選択にはRadioButtonを使うのが基本です。

7-6. WinFormsとWPFのサンプルコードを混同している

C#のトグルボタンを調べていると、WinFormsとWPFのコードが混ざってしまうことがあります。

WinFormsでは、主に次のようなプロパティやイベントを使います。

CheckBox.Checked
CheckBox.CheckedChanged
Button.Click
BackColor
ForeColor

WPFでは、次のようなプロパティやイベントを使います。

ToggleButton.IsChecked
ToggleButton.Checked
ToggleButton.Unchecked
Content
Background
Style
Trigger

WinFormsのTextやBackColorをWPFのXAMLにそのまま書いたり、WPFのIsCheckedをWinFormsのButtonで使おうとしたりするとエラーになります。まず、自分が作っているアプリがWinFormsなのかWPFなのかを確認しましょう。

8. WinForms・WPF別の完成サンプルコード

8-1. WinForms版:CheckBoxを使ったトグルボタン完成例

WinFormsでCheckBoxをトグルボタン風にする完成例です。

C#
using System;
using System.Drawing;
using System.Windows.Forms;

namespace WinFormsToggleSample
{
public partial class Form1 : Form
{
private CheckBox checkBoxToggle;

public Form1()
{
InitializeComponent();
InitializeToggleButton();
}

private void InitializeToggleButton()
{
checkBoxToggle = new CheckBox();
checkBoxToggle.Appearance = Appearance.Button;
checkBoxToggle.Width = 120;
checkBoxToggle.Height = 40;
checkBoxToggle.Left = 50;
checkBoxToggle.Top = 50;
checkBoxToggle.TextAlign = ContentAlignment.MiddleCenter;
checkBoxToggle.CheckedChanged += CheckBoxToggle_CheckedChanged;

Controls.Add(checkBoxToggle);

UpdateToggleView();
}

private void CheckBoxToggle_CheckedChanged(object sender, EventArgs e)
{
UpdateToggleView();
}

private void UpdateToggleView()
{
if (checkBoxToggle.Checked)
{
checkBoxToggle.Text = "ON";
checkBoxToggle.BackColor = Color.LightGreen;
}
else
{
checkBoxToggle.Text = "OFF";
checkBoxToggle.BackColor = Color.LightGray;
}
}
}
}

この方法は、WinFormsでトグルボタンを作る最も簡単な実装のひとつです。状態管理はCheckBoxのCheckedプロパティに任せられます。

8-2. WinForms版:Buttonを使った疑似トグルボタン完成例

Buttonを使って疑似トグルボタンを作る完成例です。

C#
using System;
using System.Drawing;
using System.Windows.Forms;

namespace WinFormsButtonToggleSample
{
public partial class Form1 : Form
{
private Button buttonToggle;
private bool isToggleOn = false;

public Form1()
{
InitializeComponent();
InitializeButtonToggle();
}

private void InitializeButtonToggle()
{
buttonToggle = new Button();
buttonToggle.Width = 120;
buttonToggle.Height = 40;
buttonToggle.Left = 50;
buttonToggle.Top = 50;
buttonToggle.Click += ButtonToggle_Click;

Controls.Add(buttonToggle);

UpdateButtonView();
}

private void ButtonToggle_Click(object sender, EventArgs e)
{
isToggleOn = !isToggleOn;
UpdateButtonView();
}

private void UpdateButtonView()
{
if (isToggleOn)
{
buttonToggle.Text = "ON";
buttonToggle.BackColor = Color.LightGreen;
}
else
{
buttonToggle.Text = "OFF";
buttonToggle.BackColor = Color.LightGray;
}
}
}
}

Buttonを使う場合は、bool変数で状態を管理する点がポイントです。

8-3. WPF版:ToggleButtonを使った基本サンプル

WPFでToggleButtonを使う基本サンプルです。

XML
<Window x:Class="WpfToggleSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ToggleButton Sample"
Height="200"
Width="300">
<Grid>
<ToggleButton x:Name="toggleButton"
Width="120"
Height="40"
Content="OFF"
Checked="ToggleButton_Checked"
Unchecked="ToggleButton_Unchecked"/>
</Grid>
</Window>

コードビハインドは次のとおりです。

C#
using System.Windows;
using System.Windows.Media;

namespace WpfToggleSample
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
UpdateToggleView();
}

private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
UpdateToggleView();
}

private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
{
UpdateToggleView();
}

private void UpdateToggleView()
{
if (toggleButton.IsChecked == true)
{
toggleButton.Content = "ON";
toggleButton.Background = Brushes.LightGreen;
}
else
{
toggleButton.Content = "OFF";
toggleButton.Background = Brushes.LightGray;
}
}
}
}

WPFではToggleButtonを使うことで、ON/OFF状態をIsCheckedで簡単に扱えます。

8-4. WPF版:StyleとTriggerを使った見た目変更サンプル

WPFらしく、StyleとTriggerで見た目を切り替えるサンプルです。

XML
<Window x:Class="WpfToggleStyleSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Toggle Style Sample"
Height="200"
Width="300">
<Window.Resources>
<Style x:Key="OnOffToggleStyle" TargetType="ToggleButton">
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Content" Value="OFF"/>
<Setter Property="Background" Value="LightGray"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="FontSize" Value="16"/>

<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="ON"/>
<Setter Property="Background" Value="LightGreen"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>

<Grid>
<ToggleButton Style="{StaticResource OnOffToggleStyle}"/>
</Grid>
</Window>

この実装では、コードビハインドを書かなくてもON/OFFの表示と背景色を切り替えられます。

8-5. WPF版:MVVM対応のトグルボタンサンプル

MVVMでToggleButtonを実装するサンプルです。

XAMLは次のようにします。

XML
<Window x:Class="WpfToggleMvvmSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MVVM Toggle Sample"
Height="200"
Width="300">
<Grid>
<ToggleButton Content="{Binding ToggleText}"
IsChecked="{Binding IsOptionEnabled, Mode=TwoWay}"
Width="120"
Height="40"/>
</Grid>
</Window>

MainWindowのコードビハインドでDataContextを設定します。

C#
using System.Windows;

namespace WpfToggleMvvmSample
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
}

ViewModelは次のとおりです。

C#
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WpfToggleMvvmSample
{
public class MainViewModel : INotifyPropertyChanged
{
private bool _isOptionEnabled;

public bool IsOptionEnabled
{
get => _isOptionEnabled;
set
{
if (_isOptionEnabled != value)
{
_isOptionEnabled = value;
OnPropertyChanged();
OnPropertyChanged(nameof(ToggleText));
}
}
}

public string ToggleText => IsOptionEnabled ? "ON" : "OFF";

public event PropertyChangedEventHandler? PropertyChanged;

private void OnPropertyChanged([CallerMemberName] string? propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}

MVVMでは、IsCheckedをViewModelのboolプロパティにバインドし、表示用テキストもViewModel側で管理すると、画面とロジックを分離できます。

9. C#トグルボタンに関するよくある質問

9-1. WinFormsにToggleButtonコントロールはある?

WinFormsには、WPFのようなToggleButtonという名前の標準コントロールはありません。

WinFormsでトグルボタンを作る場合は、主に次の方法を使います。

・CheckBoxのAppearanceをButtonにする
・Buttonとbool変数で疑似トグルボタンを作る
・ToolStripButtonのCheckOnClickを使う

最も簡単で扱いやすいのは、CheckBoxをボタン風に表示する方法です。CheckedプロパティでON/OFF状態を管理できるため、実装もシンプルです。

9-2. WPFのToggleButtonとCheckBoxは何が違う?

WPFのToggleButtonとCheckBoxは、どちらもIsCheckedプロパティを持ち、ON/OFF状態を扱えます。

違いは主に見た目です。CheckBoxはチェックマーク付きの選択UIとして使われることが多く、ToggleButtonは押された状態を持つボタンとして使われます。

内部的にはCheckBoxやRadioButtonもToggleButton系の性質を持っていますが、用途としては次のように使い分けると分かりやすいです。

ToggleButton:ボタンとしてON/OFFを切り替えたい
CheckBox:チェック項目としてON/OFFを選ばせたい
RadioButton:複数のうち1つだけ選ばせたい

9-3. トグルボタンのON/OFF状態を保存するには?

トグルボタンの状態を保存したい場合は、アプリの設定やファイル、データベースなどにbool値として保存します。

WinFormsの場合は、Checkedの値を保存します。

C#
Properties.Settings.Default.IsToggleOn = checkBoxToggle.Checked;
Properties.Settings.Default.Save();

読み込み時には、保存された値を復元します。

C#
checkBoxToggle.Checked = Properties.Settings.Default.IsToggleOn;

WPFの場合も、IsCheckedの値をboolとして保存します。

C#
bool isOn = toggleButton.IsChecked == true;

MVVMの場合は、ViewModelのboolプロパティを設定として保存すると管理しやすくなります。

9-4. トグルボタンをスイッチ風にできる?

WPFでは、ControlTemplateを使うことでトグルボタンをスイッチ風にできます。

角丸の背景と丸いつまみを配置し、IsCheckedがtrueのときにつまみの位置や背景色を変更します。設定画面のON/OFFスイッチのようなUIを作りたい場合に便利です。

WinFormsでもPanelやカスタムコントロールを使えばスイッチ風にできますが、標準コントロールだけで実装するなら、CheckBoxをボタン風にする方法が簡単です。見た目を大きく変えたい場合は、独自コントロールの作成を検討するとよいでしょう。

9-5. 複数のトグルボタンを排他的に切り替えるには?

複数のうち1つだけをONにしたい場合は、RadioButtonを使うのが基本です。

WPFでは、GroupNameを同じにすることで排他的に選択できます。

XML
<RadioButton Content="A" GroupName="Mode"/>
<RadioButton Content="B" GroupName="Mode"/>
<RadioButton Content="C" GroupName="Mode"/>

WinFormsでも、同じコンテナ内のRadioButtonは基本的に1つだけ選択されます。

どうしてもToggleButtonで排他的な動作を作りたい場合は、1つがONになったときに他のToggleButtonをOFFにする処理を書く必要があります。ただし、実装が複雑になりやすいため、排他的な選択にはRadioButtonを使う方が自然です。

まとめ

C#でトグルボタンを作る方法は、WinFormsとWPFで異なります。

WinFormsでは、CheckBoxのAppearanceをButtonに設定する方法が簡単です。CheckedプロパティでON/OFF状態を管理でき、CheckedChangedイベントで表示や処理を切り替えられます。Buttonを使って疑似トグルボタンを作る場合は、bool変数で状態を管理します。

WPFでは、ToggleButtonコントロールを使うのが基本です。IsCheckedプロパティでON/OFF状態を取得し、Checked・UncheckedイベントやStyle、Triggerを使って見た目や動作を切り替えられます。さらに、ControlTemplateを使えばスイッチ風のデザインも実装できます。

MVVMで実装する場合は、IsCheckedをViewModelのboolプロパティにTwoWayバインドし、INotifyPropertyChangedで画面表示を更新します。Contentを表示用プロパティにバインドすれば、ON/OFFに応じたテキスト切り替えも簡単に行えます。

C#のトグルボタン実装では、WinFormsとWPFで使うプロパティやイベントが異なる点に注意しましょう。WinFormsではCheckedやBackColor、WPFではIsCheckedやContent、Style、Triggerを使うのが基本です。用途に応じて、CheckBox、Button、ToggleButton、RadioButtonを使い分けることで、分かりやすく使いやすいトグルボタンを実装できます。