C#タブコントロールの使い方完全ガイド|タブ追加・切り替え・デザイン変更まで解説

はじめに

C#でWindowsフォームアプリケーションを作成するとき、画面内の情報を整理するためによく使われるのがタブコントロールです。設定画面、入力フォーム、管理画面、複数ページを持つツールなど、限られた画面領域に複数の機能をまとめたい場面で役立ちます。

C#のタブコントロールは、主にWindowsフォームのTabControlとして利用されます。タブごとにTabPageを持ち、それぞれのページにボタン、テキストボックス、ラベル、一覧表などのコントロールを配置できます。

この記事では、C#タブコントロールの基本的な使い方から、タブの追加・削除、切り替え、イベント処理、表示制御、デザイン変更、実用的なサンプルコードまでを順番に解説します。WindowsフォームでタブUIを実装したい方は、この記事を読むことで基本から応用まで理解できるようになります。

1. C#のタブコントロールとは

C#のタブコントロールとは、複数のページをタブ形式で切り替えて表示するためのUI部品です。WindowsフォームではTabControlクラスを使って実装します。

たとえば、アプリケーションの設定画面で「基本設定」「表示設定」「詳細設定」のように項目を分けたい場合、1つのフォームにすべての入力欄を並べると画面が見づらくなります。そこでタブコントロールを使うと、関連する項目ごとに画面を分割でき、操作しやすいUIを作れます。

C#タブコントロールは、単なる画面切り替えだけでなく、選択中のタブ取得、タブ切り替え時の処理、入力チェック、タブの動的追加、デザイン変更など、さまざまな用途に対応できます。

1-1. TabControlでできること

TabControlを使うと、主に次のようなことができます。

複数の画面を1つのフォーム内で切り替えて表示できます。各タブはTabPageとして管理され、それぞれに別々のコントロールを配置できます。

また、コードからタブを追加したり削除したりできます。たとえば、ユーザーがボタンを押したタイミングで新しいタブを作成する、選択中のタブを閉じるといった処理も可能です。

さらに、SelectedIndexSelectedTabを使って現在表示しているタブを切り替えたり、取得したりできます。タブ切り替え時にはイベントを使って、表示内容の更新や入力チェックを実行できます。

デザイン面では、タブの位置、サイズ、複数行表示、アイコン表示、独自描画による色変更なども設定できます。

1-2. WindowsフォームでタブUIを使うメリット

WindowsフォームでタブUIを使う大きなメリットは、画面を整理しやすくなることです。

入力項目や機能が多い画面では、すべてを1画面に詰め込むとユーザーが目的の項目を探しにくくなります。タブを使えば、関連する情報ごとに分類できるため、操作の流れがわかりやすくなります。

また、画面遷移を増やさずに複数の情報を扱える点もメリットです。別フォームを何枚も開く設計にすると、フォーム間のデータ受け渡しや状態管理が複雑になります。一方、タブコントロールであれば、1つのフォーム内で複数のページを管理できます。

設定画面、顧客情報管理、商品登録、検索条件入力、ログ表示、開発ツールなど、情報をカテゴリごとに分けたい画面では、C#タブコントロールが非常に便利です。

1-3. TabControl・TabPage・SelectedIndexの基本関係

C#のタブコントロールを理解するうえで重要なのが、TabControlTabPageSelectedIndexの関係です。

TabControlはタブ全体を表すコントロールです。フォーム上に配置する親コンテナのような役割を持ちます。

TabPageは、各タブの中身を表すページです。タブ1つにつき、基本的に1つのTabPageがあります。ボタンやテキストボックスなどのコントロールは、このTabPageの中に配置します。

SelectedIndexは、現在選択されているタブの番号を表します。インデックスは0から始まるため、最初のタブは0、2番目のタブは1、3番目のタブは2になります。

C#
// 1番目のタブを選択
tabControl1.SelectedIndex = 0;

// 2番目のタブを選択
tabControl1.SelectedIndex = 1;

// 現在選択中のタブ番号を取得
int index = tabControl1.SelectedIndex;

また、特定のTabPageを直接指定したい場合はSelectedTabを使います。

C#
tabControl1.SelectedTab = tabPage2;

このように、番号で管理する場合はSelectedIndex、ページそのものを指定する場合はSelectedTabを使うと覚えるとわかりやすいです。

1-4. WPFやWebのタブUIとの違い

C#でタブUIを作る方法は、WindowsフォームのTabControlだけではありません。WPFにもTabControlがあり、WebアプリではHTML、CSS、JavaScriptなどでタブUIを実装します。

WindowsフォームのTabControlは、ドラッグ&ドロップで簡単に配置できる点が特徴です。Visual Studioのデザイナーを使えば、コードを書かなくてもタブを追加したり、ページ内にコントロールを配置したりできます。

一方、WPFのタブコントロールは、XAMLでUIを定義し、データバインディングやスタイルを使って柔軟にデザインできます。見た目を細かく変更したい場合やMVVMパターンを使う場合はWPFが向いています。

WebのタブUIは、ブラウザ上で動作し、CSSやJavaScriptによって表示を切り替えます。レスポンシブデザインやアニメーション表現には強いですが、Windowsデスクトップアプリとは実装方法が異なります。

この記事では、Windowsフォームで使うC#タブコントロールを中心に解説します。

2. C#タブコントロールを使う準備

C#でタブコントロールを使うには、Windowsフォームアプリケーションを作成し、フォーム上にTabControlを配置します。Visual Studioを使えば、コードを書かなくても基本的な配置や設定ができます。

ここでは、Visual StudioでWindowsフォームアプリを作成し、ツールボックスからタブコントロールを配置する流れを説明します。

2-1. Visual StudioでWindowsフォームアプリを作成する

まず、Visual Studioを起動し、新しいプロジェクトを作成します。

プロジェクトテンプレートでは「Windows フォーム アプリ」を選択します。C#用のテンプレートを選び、任意のプロジェクト名を入力して作成します。

プロジェクトが作成されると、Form1が表示されます。このフォームにタブコントロールを配置していきます。

.NET Framework版と.NET版のWindowsフォームがありますが、基本的なTabControlの使い方は大きく変わりません。既存システムでは.NET Framework、これから新規作成するアプリでは新しい.NET版を使うケースが多いです。

2-2. ツールボックスからTabControlを配置する

フォームデザイナーを開いた状態で、Visual Studioの「ツールボックス」からTabControlを探します。

TabControlをフォーム上にドラッグ&ドロップすると、フォームにタブコントロールが配置されます。初期状態では、tabPage1tabPage2のように2つのタブページが作成されることが多いです。

配置されたタブコントロールは、フォーム上でサイズ変更できます。タブの中をクリックすると、そのタブページにボタンやラベルなどのコントロールを配置できます。

たとえば、tabPage1に基本情報、tabPage2に詳細情報を配置すれば、簡単なタブ画面を作れます。

2-3. プロパティ画面でタブ名やサイズを設定する

タブ名を変更するには、対象のTabPageを選択し、プロパティウィンドウのTextプロパティを変更します。

たとえば、tabPage1Textを「基本設定」、tabPage2Textを「詳細設定」に変更すると、画面上のタブ見出しもその名前に変わります。

コードで変更する場合は、次のように書きます。

C#
tabPage1.Text = "基本設定";
tabPage2.Text = "詳細設定";

タブコントロール全体のサイズは、Sizeプロパティで設定できます。

C#
tabControl1.Width = 600;
tabControl1.Height = 400;

ただし、フォームサイズに合わせて自動的に広げたい場合は、次に説明するDockAnchorを使う方が便利です。

2-4. DockやAnchorで画面サイズに合わせて配置する

フォームのサイズ変更に合わせてタブコントロールも広げたい場合は、DockまたはAnchorを使います。

DockプロパティをFillに設定すると、タブコントロールがフォーム全体に広がります。

C#
tabControl1.Dock = DockStyle.Fill;

フォームの一部に配置しつつ、上下左右に追従させたい場合はAnchorを使います。

C#
tabControl1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;

Dockは親コンテナ全体にぴったり配置したい場合に便利です。Anchorは、余白や他のコントロールとの位置関係を保ちながらサイズ変更したい場合に使います。

タブコントロールを実用的な画面で使う場合、フォームサイズ変更への対応は重要です。特に一覧表や入力フォームをタブ内に配置する場合は、DockAnchorを適切に設定しておきましょう。

3. タブページの基本操作

C#タブコントロールでは、タブページをデザイナーで追加・削除する方法と、コードで追加・削除する方法があります。

固定された画面構成であればデザイナー操作だけで十分ですが、ユーザー操作に応じてタブを増やしたい場合や、ファイルごとにタブを開くようなアプリではコードによる操作が必要です。

3-1. デザイナーでタブを追加・削除する

Visual Studioのデザイナー上でTabControlを選択すると、右上に小さな三角形のスマートタグが表示されることがあります。そこから「タブの追加」「タブの削除」を選べます。

また、プロパティウィンドウのTabPagesコレクションを編集することでも、タブページを追加・削除できます。

デザイナーで追加したタブは、フォームのコード内でtabPage1tabPage2のような名前で扱えます。名前をわかりやすくしたい場合は、Nameプロパティを変更します。

たとえば、基本設定用のタブならtabPageBasic、詳細設定用のタブならtabPageDetailのようにしておくと、コードが読みやすくなります。

3-2. コードでTabPageを追加する

コードでタブを追加するには、TabPageのインスタンスを作成し、TabControl.TabPages.Addで追加します。

C#
TabPage newPage = new TabPage();
newPage.Text = "新しいタブ";

tabControl1.TabPages.Add(newPage);

作成したタブページにコントロールを追加することもできます。

C#
TabPage newPage = new TabPage("入力画面");

TextBox textBox = new TextBox();
textBox.Location = new Point(20, 20);
textBox.Width = 200;

Button button = new Button();
button.Text = "登録";
button.Location = new Point(20, 60);

newPage.Controls.Add(textBox);
newPage.Controls.Add(button);

tabControl1.TabPages.Add(newPage);

このようにすると、実行中に新しいタブを作成し、その中に入力欄やボタンを配置できます。

3-3. コードでTabPageを削除する

タブを削除するには、TabPages.RemoveまたはTabPages.RemoveAtを使います。

Removeは削除したいTabPageを指定します。

C#
tabControl1.TabPages.Remove(tabPage2);

RemoveAtはインデックス番号を指定します。

C#
tabControl1.TabPages.RemoveAt(1);

選択中のタブを削除したい場合は、次のように書けます。

C#
if (tabControl1.SelectedTab != null)
{
tabControl1.TabPages.Remove(tabControl1.SelectedTab);
}

ただし、タブを削除するとSelectedIndexが変わる場合があります。タブ番号に依存した処理を書いている場合は、削除後のインデックスに注意しましょう。

3-4. タブのタイトルを変更する

タブのタイトルは、TabPage.Textプロパティで変更します。

C#
tabPage1.Text = "ユーザー情報";

選択中のタブのタイトルを変更する場合は、次のように書きます。

C#
if (tabControl1.SelectedTab != null)
{
tabControl1.SelectedTab.Text = "変更後のタイトル";
}

ファイル編集アプリのように、開いたファイル名をタブ名に表示する場合にもこの方法が使えます。

C#
TabPage page = new TabPage();
page.Text = "sample.txt";
tabControl1.TabPages.Add(page);

タブ名が長すぎると見づらくなるため、必要に応じて短縮表示を検討しましょう。

3-5. タブ内にボタンやテキストボックスを配置する

タブ内にコントロールを配置するには、対象のTabPage.Controlsに追加します。

C#
Label label = new Label();
label.Text = "名前";
label.Location = new Point(20, 20);

TextBox textBox = new TextBox();
textBox.Location = new Point(80, 18);
textBox.Width = 200;

tabPage1.Controls.Add(label);
tabPage1.Controls.Add(textBox);

デザイナーを使う場合は、対象のタブページを選択した状態で、ツールボックスからボタンやテキストボックスをドラッグ&ドロップします。

注意点として、タブページの外にコントロールを配置してしまうと、タブ切り替えの影響を受けません。タブ内で表示を切り替えたいコントロールは、必ず対象のTabPageの中に配置しましょう。

4. タブの切り替え方法

C#タブコントロールでは、ユーザーがタブをクリックして切り替えるだけでなく、コードから任意のタブに切り替えることもできます。

タブ切り替えには、主にSelectedIndexSelectedTabを使います。番号で指定するならSelectedIndex、ページオブジェクトで指定するならSelectedTabです。

4-1. SelectedIndexで表示するタブを切り替える

SelectedIndexを設定すると、指定した番号のタブに切り替えられます。

C#
// 最初のタブを表示
tabControl1.SelectedIndex = 0;

// 2番目のタブを表示
tabControl1.SelectedIndex = 1;

インデックスは0から始まるため、1番目のタブは0です。

存在しない番号を指定するとエラーになる可能性があるため、タブ数を確認してから切り替えると安全です。

C#
if (tabControl1.TabPages.Count > 1)
{
tabControl1.SelectedIndex = 1;
}

動的にタブを追加・削除する場合は、現在のタブ数を確認する習慣をつけると、実行時エラーを防ぎやすくなります。

4-2. SelectedTabで特定のTabPageを選択する

SelectedTabを使うと、特定のTabPageを直接選択できます。

C#
tabControl1.SelectedTab = tabPage2;

SelectedIndexは番号指定なので、タブの順番が変わると意図しないタブを選んでしまうことがあります。一方、SelectedTabはページそのものを指定するため、対象が明確です。

動的に作成したタブを選択する場合にも使えます。

C#
TabPage newPage = new TabPage("新規タブ");
tabControl1.TabPages.Add(newPage);
tabControl1.SelectedTab = newPage;

タブを追加した直後にそのタブを表示したい場合は、この書き方が便利です。

4-3. ボタンクリックで次のタブ・前のタブへ移動する

ウィザード形式の画面では、「次へ」「戻る」ボタンでタブを切り替えたいことがあります。

次のタブへ移動する例です。

C#
private void buttonNext_Click(object sender, EventArgs e)
{
if (tabControl1.SelectedIndex < tabControl1.TabPages.Count - 1)
{
tabControl1.SelectedIndex++;
}
}

前のタブへ移動する例です。

C#
private void buttonPrev_Click(object sender, EventArgs e)
{
if (tabControl1.SelectedIndex > 0)
{
tabControl1.SelectedIndex--;
}
}

このように境界チェックを入れておくと、最初のタブより前や最後のタブより後に移動しようとしてエラーになるのを防げます。

4-4. 現在選択中のタブを取得する

現在選択中のタブ番号はSelectedIndexで取得できます。

C#
int index = tabControl1.SelectedIndex;
MessageBox.Show($"現在のタブ番号: {index}");

現在選択中のTabPageSelectedTabで取得できます。

C#
TabPage currentPage = tabControl1.SelectedTab;

if (currentPage != null)
{
MessageBox.Show($"現在のタブ: {currentPage.Text}");
}

タブごとに処理を分けたい場合は、SelectedTabを比較するとわかりやすいです。

C#
if (tabControl1.SelectedTab == tabPageBasic)
{
// 基本設定タブの処理
}
else if (tabControl1.SelectedTab == tabPageDetail)
{
// 詳細設定タブの処理
}

4-5. タブ切り替え時に処理を実行する

タブが切り替わったタイミングで処理を実行したい場合は、SelectedIndexChangedイベントを使います。

C#
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
MessageBox.Show("タブが切り替わりました");
}

たとえば、一覧タブに切り替わったときにデータを再読み込みする処理を書けます。

C#
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
if (tabControl1.SelectedTab == tabPageList)
{
LoadData();
}
}

private void LoadData()
{
// データ読み込み処理
}

タブ切り替え後に処理する場合はSelectedIndexChanged、切り替え前に判定したい場合はSelectingイベントを使います。

5. タブコントロールのイベント活用

C#タブコントロールでは、タブ切り替えに関するイベントを活用すると、より実用的な画面を作れます。

代表的なイベントには、切り替え後に発生するSelectedIndexChanged、切り替え前に発生するSelecting、切り替え後の詳細制御に使えるSelectedなどがあります。

ここでは、よく使うイベントを中心に解説します。

5-1. SelectedIndexChangedイベントの使い方

SelectedIndexChangedイベントは、選択中のタブが変わったときに発生します。

C#
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
TabPage page = tabControl1.SelectedTab;

if (page != null)
{
labelStatus.Text = $"{page.Text}を表示中です";
}
}

このイベントは、タブ切り替え後の画面更新に向いています。

たとえば、検索結果タブが表示されたときに一覧を更新する、ログタブが表示されたときに最新ログを読み込む、設定タブが表示されたときに現在の設定値を反映する、といった使い方ができます。

5-2. Selectingイベントでタブ切り替え前に判定する

Selectingイベントは、タブが選択される前に発生します。切り替えを許可するかどうか判断したい場合に使います。

C#
private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (e.TabPage == tabPageConfirm)
{
MessageBox.Show("確認タブへ移動します");
}
}

Selectingイベントでは、e.TabPageで移動先のタブを取得できます。また、e.Cancel = true;を設定すると、タブ切り替えをキャンセルできます。

5-3. 特定条件でタブ移動をキャンセルする

入力が完了していない場合に次のタブへ移動させたくない場合は、Selectingイベントで判定します。

C#
private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (tabControl1.SelectedTab == tabPageInput && e.TabPage == tabPageConfirm)
{
if (string.IsNullOrWhiteSpace(textBoxName.Text))
{
MessageBox.Show("名前を入力してください。");
e.Cancel = true;
}
}
}

この例では、入力タブから確認タブへ移動する前に、名前が入力されているかをチェックしています。未入力の場合はe.Cancel = trueによってタブ移動を中止します。

ウィザード形式の入力画面や、必須項目のある設定画面でよく使う実装です。

5-4. タブごとに入力チェックや画面更新を行う

タブごとに処理を分ける場合は、SelectedTabe.TabPageを使って条件分岐します。

C#
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
if (tabControl1.SelectedTab == tabPageUser)
{
UpdateUserInfo();
}
else if (tabControl1.SelectedTab == tabPageOrder)
{
UpdateOrderInfo();
}
else if (tabControl1.SelectedTab == tabPageSetting)
{
UpdateSettingInfo();
}
}

処理が長くなる場合は、タブごとにメソッドを分けると保守しやすくなります。

C#
private void UpdateUserInfo()
{
// ユーザー情報の更新
}

private void UpdateOrderInfo()
{
// 注文情報の更新
}

private void UpdateSettingInfo()
{
// 設定情報の更新
}

イベント内にすべての処理を書き込むと読みにくくなるため、実務では処理をメソッド化するのがおすすめです。

5-5. 初期表示時に任意のタブを選択する

フォーム表示時に特定のタブを選択したい場合は、フォームのLoadイベントでSelectedIndexまたはSelectedTabを設定します。

C#
private void Form1_Load(object sender, EventArgs e)
{
tabControl1.SelectedIndex = 0;
}

特定のタブページを指定する場合は次のようにします。

C#
private void Form1_Load(object sender, EventArgs e)
{
tabControl1.SelectedTab = tabPageSetting;
}

ただし、タブが動的に追加される場合は、対象のタブが追加された後に選択する必要があります。まだ存在しないタブを選択しようとすると、期待通りに動作しません。

6. タブの表示・非表示・有効化を制御する

C#のWindowsフォームのTabPageには、通常のコントロールのように簡単にタブ見出しだけを非表示にする仕組みがありません。そのため、タブを隠したい場合はTabPagesコレクションから一時的に削除し、必要になったら再度追加する方法がよく使われます。

また、タブを選択できないようにしたい場合は、Selectingイベントでキャンセルする方法が実用的です。

6-1. タブを一時的に非表示にする考え方

TabPage.Visible = false;のように書いても、Windowsフォームのタブページでは期待通りにタブ見出しが消えない場合があります。

そのため、タブを非表示にしたい場合は、次の考え方を使います。

非表示にしたいタブをTabControl.TabPagesから削除します。再表示したいときは、保持しておいたTabPageを再びTabPagesに追加します。

重要なのは、削除する前にTabPageの参照を保持しておくことです。参照を失うと、再表示したいときに同じタブを戻せなくなります。

6-2. TabPages.RemoveとAddで表示を切り替える

タブを一時的に非表示にする例です。

C#
private TabPage hiddenPage;

private void HideDetailTab()
{
hiddenPage = tabPageDetail;
tabControl1.TabPages.Remove(tabPageDetail);
}

再表示する場合は、保持しておいたTabPageを追加します。

C#
private void ShowDetailTab()
{
if (hiddenPage != null && !tabControl1.TabPages.Contains(hiddenPage))
{
tabControl1.TabPages.Add(hiddenPage);
}
}

特定の位置に戻したい場合は、Insertを使います。

C#
tabControl1.TabPages.Insert(1, hiddenPage);

この方法を使えば、権限によって特定のタブを表示しない、設定によって詳細タブを隠す、といった制御ができます。

6-3. タブを無効化して選択できないようにする方法

TabPageには、タブ見出しだけを簡単に無効化する標準的な仕組みがありません。そこで、タブを選択させたくない場合はSelectingイベントでキャンセルします。

C#
private bool canOpenDetailTab = false;

private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (e.TabPage == tabPageDetail && !canOpenDetailTab)
{
MessageBox.Show("詳細タブはまだ選択できません。");
e.Cancel = true;
}
}

この例では、canOpenDetailTabfalseの間は詳細タブへ移動できません。

入力完了後に詳細タブを許可する場合は、次のようにフラグを変更します。

C#
private void buttonComplete_Click(object sender, EventArgs e)
{
canOpenDetailTab = true;
tabControl1.SelectedTab = tabPageDetail;
}

6-4. インデックスがずれる原因と対策

タブを追加・削除すると、SelectedIndexや各タブのインデックスが変わります。

たとえば、3つのタブがある状態で2番目のタブを削除すると、3番目のタブが2番目の位置に移動します。そのため、インデックス番号に依存した処理を書いていると、削除後に意図しないタブを操作してしまうことがあります。

対策として、可能な限りSelectedIndexだけでなくSelectedTabTabPageの参照を使うのがおすすめです。

C#
if (tabControl1.SelectedTab == tabPageSetting)
{
// 設定タブの処理
}

また、タブ名で判定する場合はNameプロパティを利用できます。

C#
if (tabControl1.SelectedTab.Name == "tabPageSetting")
{
// 設定タブの処理
}

ただし、Textプロパティは画面表示用のタイトルなので、ユーザー向け文言の変更によって判定が壊れる可能性があります。内部処理ではNameや参照を使う方が安全です。

6-5. 画面遷移のようにタブを使う実装例

タブコントロールを画面遷移のように使うこともできます。たとえば、「入力」「確認」「完了」という3ステップの画面をタブで表現する例です。

C#
private void buttonNextToConfirm_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(textBoxName.Text))
{
MessageBox.Show("名前を入力してください。");
return;
}

labelConfirmName.Text = textBoxName.Text;
tabControl1.SelectedTab = tabPageConfirm;
}

private void buttonSubmit_Click(object sender, EventArgs e)
{
// 登録処理
tabControl1.SelectedTab = tabPageComplete;
}

ユーザーにタブ見出しを直接クリックさせたくない場合は、Selectingイベントで現在のステップ以外への移動を制限できます。

C#
private int currentStep = 0;

private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (tabControl1.TabPages.IndexOf(e.TabPage) > currentStep)
{
e.Cancel = true;
}
}

ただし、画面遷移が複雑になる場合は、タブコントロールではなく複数フォームやUserControlによる画面切り替えを検討した方がよい場合もあります。

7. タブコントロールのデザイン変更

C#タブコントロールは、標準のままでも使えますが、プロパティや描画処理を変更することで、見た目を調整できます。

タブのサイズ、位置、複数行表示、アイコン表示、色変更などを行うことで、アプリの用途に合ったタブUIにできます。

7-1. タブの幅・高さを変更する

タブの幅や高さを変更するには、SizeModeItemSizeを使います。

C#
tabControl1.SizeMode = TabSizeMode.Fixed;
tabControl1.ItemSize = new Size(120, 30);

SizeModeFixedにすると、すべてのタブが指定したサイズで表示されます。

タブ名の長さに合わせて自動調整したい場合は、標準のままでも問題ありません。ただし、タブの幅を揃えたい場合や、ボタン風の見た目にしたい場合はItemSizeを設定するとよいでしょう。

7-2. タブの位置を上・下・左・右に変更する

タブの表示位置は、Alignmentプロパティで変更できます。

C#
// 上
tabControl1.Alignment = TabAlignment.Top;

// 下
tabControl1.Alignment = TabAlignment.Bottom;

// 左
tabControl1.Alignment = TabAlignment.Left;

// 右
tabControl1.Alignment = TabAlignment.Right;

一般的には上部に表示するTopが多く使われます。画面構成によっては、左側にカテゴリを並べるようなUIにすることもできます。

ただし、左や右に配置すると、標準描画では文字の向きや見た目が期待通りにならない場合があります。デザインを重視する場合は、独自描画や別のUI構成も検討しましょう。

7-3. タブを複数行で表示する

タブの数が多い場合は、Multilineプロパティをtrueにすると複数行で表示できます。

C#
tabControl1.Multiline = true;

複数行にすると、タブが折り返されて表示されるため、横幅に収まりきらない場合に便利です。

ただし、タブが多すぎると画面が見づらくなります。タブ数が多い場合は、タブを分類し直す、リストやツリーを使う、別画面に分けるなどのUI改善も検討しましょう。

7-4. タブにアイコンを表示する

タブにアイコンを表示するには、ImageListを使います。

まず、フォームにImageListを配置し、画像を登録します。その後、TabControl.ImageListに設定します。

C#
tabControl1.ImageList = imageList1;
tabPage1.ImageIndex = 0;
tabPage2.ImageIndex = 1;

画像キーを使う場合は、ImageKeyを指定します。

C#
tabPage1.ImageKey = "home";
tabPage2.ImageKey = "setting";

アイコンを表示すると、タブの意味が視覚的にわかりやすくなります。設定、検索、一覧、ユーザー、ログなど、機能ごとにアイコンを付けると操作性が向上します。

7-5. DrawItemでタブの色や文字をカスタマイズする

タブの色や文字を細かく変更したい場合は、DrawModeOwnerDrawFixedに設定し、DrawItemイベントで独自描画します。

C#
private void Form1_Load(object sender, EventArgs e)
{
tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
tabControl1.DrawItem += tabControl1_DrawItem;
}

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
TabPage page = tabControl1.TabPages[e.Index];
Rectangle rect = tabControl1.GetTabRect(e.Index);

bool selected = (e.Index == tabControl1.SelectedIndex);

using (Brush backBrush = new SolidBrush(selected ? Color.LightBlue : Color.LightGray))
using (Brush textBrush = new SolidBrush(Color.Black))
{
e.Graphics.FillRectangle(backBrush, rect);

StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;

e.Graphics.DrawString(page.Text, tabControl1.Font, textBrush, rect, sf);
}
}

この例では、選択中のタブを水色、それ以外をグレーで描画しています。

独自描画を使うと自由度は上がりますが、描画処理が複雑になりやすいです。最初は標準プロパティで調整し、必要な場合だけDrawItemを使うとよいでしょう。

7-6. フラットデザイン風に見せるポイント

Windowsフォームの標準タブは、やや古い見た目に感じることがあります。フラットデザイン風に見せたい場合は、次のような工夫が有効です。

タブの高さを少し大きめにして、余白を確保します。ItemSizeで高さを調整すると、押しやすく見やすいタブになります。

選択中のタブと未選択のタブで背景色を変えます。DrawItemを使えば、選択中のタブだけ色を変えることができます。

文字を中央揃えにし、必要以上に罫線や立体感を出さないようにします。標準のWindowsフォームだけで完全なモダンUIを作るのは難しいですが、色、余白、フォントを整えるだけでも印象は大きく変わります。

より本格的なデザインが必要な場合は、WPFや外部UIライブラリの利用も検討するとよいでしょう。

8. 実用的なサンプルコード集

ここからは、C#タブコントロールでよく使う実用的なサンプルコードを紹介します。

タブの動的追加、閉じるボタン風の実装、タブ切り替え時の更新、入力フォームの分割、設定画面のタブ化など、実務で使いやすいパターンを確認していきましょう。

8-1. タブを動的に追加するサンプル

ボタンをクリックするたびに新しいタブを追加するサンプルです。

C#
private int tabCount = 1;

private void buttonAddTab_Click(object sender, EventArgs e)
{
TabPage page = new TabPage();
page.Text = $"タブ{tabCount}";
page.Name = $"tabPageDynamic{tabCount}";

TextBox textBox = new TextBox();
textBox.Multiline = true;
textBox.Dock = DockStyle.Fill;

page.Controls.Add(textBox);
tabControl1.TabPages.Add(page);
tabControl1.SelectedTab = page;

tabCount++;
}

メモ帳風のアプリや、複数ファイルをタブで開くアプリに応用できます。

8-2. タブを閉じるボタン付きにするサンプル

標準のTabControlには、タブごとの閉じるボタンはありません。簡易的に実装する場合は、タブ名に「×」を付け、クリック位置で閉じる処理を行います。

C#
private void Form1_Load(object sender, EventArgs e)
{
tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
tabControl1.DrawItem += tabControl1_DrawItem;
tabControl1.MouseDown += tabControl1_MouseDown;
}

private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
TabPage page = tabControl1.TabPages[e.Index];
Rectangle rect = tabControl1.GetTabRect(e.Index);

string text = page.Text + " ×";

using (Brush brush = new SolidBrush(Color.Black))
{
e.Graphics.DrawString(text, tabControl1.Font, brush, rect);
}
}

private void tabControl1_MouseDown(object sender, MouseEventArgs e)
{
for (int i = 0; i < tabControl1.TabPages.Count; i++)
{
Rectangle rect = tabControl1.GetTabRect(i);
Rectangle closeRect = new Rectangle(rect.Right - 20, rect.Top + 4, 16, 16);

if (closeRect.Contains(e.Location))
{
tabControl1.TabPages.RemoveAt(i);
break;
}
}
}

実務で使う場合は、閉じる前に保存確認を出すなどの処理を追加すると安全です。

8-3. タブ切り替えで表示内容を更新するサンプル

タブを切り替えたときに、選択中のタブに応じて表示内容を更新する例です。

C#
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
if (tabControl1.SelectedTab == tabPageList)
{
RefreshList();
}
else if (tabControl1.SelectedTab == tabPageLog)
{
RefreshLog();
}
}

private void RefreshList()
{
// 一覧データを再読み込みする処理
}

private void RefreshLog()
{
// ログを再読み込みする処理
}

一覧画面やログ画面では、タブを表示したタイミングで最新データに更新すると、ユーザーにとってわかりやすい画面になります。

8-4. 入力フォームをタブで分けるサンプル

入力項目が多い場合は、タブでカテゴリ分けすると見やすくなります。

たとえば、顧客登録画面を「基本情報」「住所情報」「備考」に分ける場合です。

C#
private void buttonConfirm_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(textBoxName.Text))
{
MessageBox.Show("氏名を入力してください。");
tabControl1.SelectedTab = tabPageBasic;
textBoxName.Focus();
return;
}

if (string.IsNullOrWhiteSpace(textBoxAddress.Text))
{
MessageBox.Show("住所を入力してください。");
tabControl1.SelectedTab = tabPageAddress;
textBoxAddress.Focus();
return;
}

MessageBox.Show("入力内容に問題ありません。");
}

入力チェックでエラーがあった場合、該当するタブへ自動的に切り替えると、ユーザーが修正箇所を見つけやすくなります。

8-5. 設定画面をタブ化するサンプル

設定画面では、カテゴリごとにタブを分けると管理しやすくなります。

C#
private void Form1_Load(object sender, EventArgs e)
{
tabPageGeneral.Text = "基本";
tabPageDisplay.Text = "表示";
tabPageNetwork.Text = "通信";
}

private void buttonSave_Click(object sender, EventArgs e)
{
SaveGeneralSettings();
SaveDisplaySettings();
SaveNetworkSettings();

MessageBox.Show("設定を保存しました。");
}

private void SaveGeneralSettings()
{
// 基本設定の保存
}

private void SaveDisplaySettings()
{
// 表示設定の保存
}

private void SaveNetworkSettings()
{
// 通信設定の保存
}

設定項目ごとに保存処理をメソッド化しておくと、あとから項目が増えた場合でも修正しやすくなります。

9. よくあるエラーと解決方法

C#タブコントロールを使っていると、SelectedIndexが想定と違う、削除したタブを戻せない、タブ内のコントロールが取得できない、イベントが何度も発生する、デザイン変更が反映されないといった問題が起こることがあります。

ここでは、よくある原因と解決方法を紹介します。

9-1. SelectedIndexが意図した番号にならない

SelectedIndexは0から始まります。最初のタブは0、2番目のタブは1です。

C#
tabControl1.SelectedIndex = 0; // 1番目のタブ
tabControl1.SelectedIndex = 1; // 2番目のタブ

また、タブを削除したり追加したりすると、インデックスが変わります。動的にタブを操作する場合は、番号だけに依存しないようにしましょう。

安全に処理するには、タブ数を確認します。

C#
if (tabControl1.TabPages.Count > 2)
{
tabControl1.SelectedIndex = 2;
}

特定のタブを選びたい場合は、SelectedTabを使う方が安全です。

C#
tabControl1.SelectedTab = tabPageSetting;

9-2. 削除したタブを再表示できない

TabPages.Removeでタブを削除したあと、参照を保持していないと同じタブを再表示しづらくなります。

悪い例です。

C#
tabControl1.TabPages.Remove(tabPageDetail);

このコード自体は問題ありませんが、再表示する処理を考えていないと戻せません。

再表示したい場合は、フィールド変数などで保持しておきます。

C#
private TabPage detailPage;

private void HideTab()
{
detailPage = tabPageDetail;
tabControl1.TabPages.Remove(detailPage);
}

private void ShowTab()
{
if (detailPage != null && !tabControl1.TabPages.Contains(detailPage))
{
tabControl1.TabPages.Add(detailPage);
}
}

9-3. タブ内のコントロールを取得できない

タブ内のコントロールを取得するには、対象のTabPage.Controlsから探します。

C#
TextBox textBox = tabPage1.Controls["textBoxName"] as TextBox;

if (textBox != null)
{
MessageBox.Show(textBox.Text);
}

ただし、コントロールがPanelやGroupBoxの中に入っている場合、TabPage.Controlsを直接探しても見つからないことがあります。その場合は、再帰的に検索する必要があります。

C#
private Control FindControlRecursive(Control parent, string name)
{
foreach (Control control in parent.Controls)
{
if (control.Name == name)
{
return control;
}

Control found = FindControlRecursive(control, name);
if (found != null)
{
return found;
}
}

return null;
}

使い方は次の通りです。

C#
TextBox textBox = FindControlRecursive(tabPage1, "textBoxName") as TextBox;

if (textBox != null)
{
MessageBox.Show(textBox.Text);
}

9-4. タブ切り替えイベントが何度も発生する

SelectedIndexChangedは、ユーザー操作だけでなく、コードでSelectedIndexSelectedTabを変更したときにも発生します。

そのため、イベント内でさらにタブを切り替える処理を書くと、イベントが連続して発生する場合があります。

対策として、処理中フラグを使います。

C#
private bool isChangingTab = false;

private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
if (isChangingTab)
{
return;
}

try
{
isChangingTab = true;

// タブ切り替え時の処理
}
finally
{
isChangingTab = false;
}
}

また、初期化中にイベントを発生させたくない場合も、同じようにフラグで制御できます。

9-5. デザイン変更が反映されない

タブの色や文字を変更するためにDrawItemを使う場合、DrawModeを設定していないと独自描画が有効になりません。

C#
tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;

また、DrawItemイベントが正しく関連付けられているか確認しましょう。

C#
tabControl1.DrawItem += tabControl1_DrawItem;

デザイナーでイベントを設定した場合と、コードでイベントを設定した場合が重複していると、同じ処理が複数回実行されることがあります。イベントの登録箇所も確認しましょう。

10. C#タブコントロール実装時の注意点

C#タブコントロールは便利ですが、何でもタブで分ければよいわけではありません。タブ数が増えすぎると逆に使いにくくなり、管理も複雑になります。

実装時は、画面構成、タブ数、データ管理、保守性を意識することが大切です。

10-1. タブ数が多すぎる場合のUI改善

タブが多すぎると、ユーザーは目的のタブを探しにくくなります。特に横幅に収まりきらないほどタブが増えると、画面の見た目も悪くなります。

タブ数が多い場合は、カテゴリを整理しましょう。似た項目をまとめる、使用頻度の低い項目を詳細設定に移す、タブではなくリストやツリーで選択するなどの方法があります。

Multilineを使って複数行表示にすることもできますが、根本的にタブが多すぎる場合はUI設計を見直した方がよいです。

10-2. タブと画面遷移を使い分ける基準

タブは、同じ画面内で関連する情報を切り替える場合に向いています。

たとえば、ユーザー情報の「基本情報」「住所」「履歴」のように、同じ対象に関する情報を分ける場合はタブが適しています。

一方で、処理の流れが明確に分かれている場合や、前の画面に戻る必要がある場合は、画面遷移やウィザード形式の方が向いていることがあります。

タブは自由に切り替えられるUIなので、順番に入力させたい処理では、Selectingイベントで制限するか、別の画面構成を検討しましょう。

10-3. 保守しやすいTabPage管理の書き方

タブを管理するときは、インデックス番号だけに頼らないことが重要です。

次のようなコードは、タブの順番が変わると壊れやすくなります。

C#
if (tabControl1.SelectedIndex == 2)
{
// 設定タブの処理
}

より安全なのは、TabPageの参照で判定する方法です。

C#
if (tabControl1.SelectedTab == tabPageSetting)
{
// 設定タブの処理
}

また、動的に作成するタブには、わかりやすいNameを付けておきましょう。

C#
TabPage page = new TabPage("ログ");
page.Name = "tabPageLog";

タブごとの処理はメソッド化し、イベント内を短く保つと読みやすくなります。

10-4. UserControlと組み合わせて複雑な画面を整理する

タブ内の画面が複雑になってきた場合は、UserControlを使うと整理しやすくなります。

タブページに直接大量のコントロールを置くのではなく、機能ごとにUserControlを作成し、それをTabPageに配置します。

C#
UserControl userControl = new UserControlBasic();
userControl.Dock = DockStyle.Fill;

tabPageBasic.Controls.Add(userControl);

この方法を使うと、各タブの処理を別ファイルに分けられるため、コードの見通しがよくなります。

たとえば、基本設定タブはBasicSettingControl、表示設定タブはDisplaySettingControl、通信設定タブはNetworkSettingControlのように分けると、保守しやすい構成になります。

大規模なWindowsフォームアプリでは、タブコントロールとUserControlを組み合わせる設計が非常に有効です。

まとめ

C#タブコントロールは、Windowsフォームアプリケーションで複数の画面や情報を整理して表示するために便利なUI部品です。TabControlをフォームに配置し、TabPageごとにコントロールを追加することで、設定画面や入力フォーム、一覧画面などをわかりやすく構成できます。

基本操作では、デザイナーからタブを追加・削除したり、コードでTabPageを動的に追加したりできます。タブの切り替えにはSelectedIndexSelectedTabを使い、切り替え時の処理にはSelectedIndexChangedSelectingイベントを活用します。

タブを非表示にしたい場合は、TabPages.RemoveAddを使って表示を切り替える方法が実用的です。タブを選択できないようにしたい場合は、Selectingイベントでe.Cancel = trueを設定します。

デザイン面では、タブのサイズ、位置、複数行表示、アイコン表示、DrawItemによる独自描画などを使って見た目を調整できます。標準のタブコントロールでも、工夫次第で使いやすいUIを作れます。

実装時は、タブ数を増やしすぎないこと、インデックス番号だけに依存しないこと、複雑な画面ではUserControlと組み合わせることが大切です。

C#タブコントロールを正しく使えば、見やすく操作しやすいWindowsフォームアプリを効率よく作成できます。