C#のタブ完全ガイド|TabControlの使い方・追加/切り替え・デザイン変更まで解説
はじめに
C#で「タブ」を扱いたいとき、主に2つの意味があります。1つは画面上で複数のページを切り替えるUI部品としてのタブ、もう1つは文字列の中で空白位置をそろえるためのタブ文字です。
この記事では、特にWindowsフォームアプリケーションでよく使われるTabControlを中心に、C#でタブを追加する方法、切り替える方法、削除する方法、イベント処理、デザイン変更、実用的な実装パターンまで解説します。あわせて、WPFのTabControlや文字列のタブ文字\tとの違いも紹介します。
「C#でタブ画面を作りたい」「TabControlの使い方を基礎から知りたい」「動的にタブを追加したい」「タブの色やデザインを変更したい」という方は、この記事を読むことで一通りの実装イメージをつかめます。
1. C#のタブとは?TabControlでできること
C#でタブという言葉が出てきた場合、文脈によって意味が変わります。まずは、C#におけるタブの主な意味を整理しておきましょう。
1-1. C#における「タブ」の主な意味
C#で「タブ」と呼ばれるものには、主に次のような種類があります。
| 種類 | 内容 | 例 |
|---|---|---|
| UIのタブ | 画面を複数ページに分けて切り替える部品 | TabControl、TabPage |
| タブ文字 | 文字列内で間隔を空ける制御文字 | "\t" |
| エディタのタブ | Visual Studioなどでファイルを切り替える領域 | コード編集画面のタブ |
| ブラウザ風タブ | Webブラウザのようにページを増減できるUI | 動的に追加・削除するタブ |
この記事で主に扱うのは、画面UIとしてのタブです。C#のWinFormsではTabControl、WPFではTabControlとTabItemを使ってタブUIを作成します。
1-2. この記事で扱うTabControlとは
TabControlとは、複数のページをタブ形式で切り替えられるUIコントロールです。WinFormsでは、TabControlの中に複数のTabPageを追加し、それぞれのタブページにボタン、テキストボックス、ラベル、一覧表などのコントロールを配置します。
たとえば、設定画面を次のように分けたい場合に便利です。
| タブ名 | 表示する内容 |
|---|---|
| 基本設定 | ユーザー名、言語、テーマ |
| 通知設定 | メール通知、プッシュ通知 |
| 詳細設定 | ログ出力、保存先、詳細オプション |
1つのフォームにすべての項目を詰め込むと画面が見づらくなりますが、TabControlを使えば関連する項目ごとに整理できます。
1-3. TabControlを使う代表的な場面
C#のTabControlは、次のような画面でよく使われます。
| 使用場面 | 例 |
|---|---|
| 設定画面 | 基本設定、表示設定、詳細設定を分ける |
| 入力フォーム | 顧客情報、請求情報、履歴情報を分ける |
| 管理画面 | ユーザー管理、商品管理、ログ管理を分ける |
| エディタ画面 | 複数ファイルをタブで切り替える |
| ブラウザ風UI | ページごとにタブを追加・削除する |
| 検索画面 | 条件入力、検索結果、詳細情報を分ける |
タブは「同じ画面の中で、関連する複数の内容を切り替える」場合に向いています。
1-4. WinForms・WPF・ASP.NETでのタブ実装の違い
C#でアプリケーションを作る環境によって、タブの実装方法は異なります。
| 種類 | 主な実装方法 | 特徴 |
|---|---|---|
| WinForms | System.Windows.Forms.TabControl | デザイナーで簡単に配置できる |
| WPF | TabControl、TabItem | XAMLで柔軟にデザインできる |
| ASP.NET | HTML、CSS、JavaScript、Bootstrapなど | Webブラウザ上で動作する |
| MAUI | TabbedPageなど | モバイル・クロスプラットフォーム向け |
この記事では、まずWinFormsのTabControlを中心に解説し、後半でWPFの基本にも触れます。
2. C#のTabControlの基本構成
TabControlを使うには、まずTabControl、TabPage、SelectedTabの関係を理解しておく必要があります。
2-1. TabControl・TabPage・SelectedTabの関係
WinFormsのタブUIは、主に次の3つで構成されます。
| 要素 | 役割 |
|---|---|
TabControl | タブ全体を管理する親コントロール |
TabPage | 各タブの中身となるページ |
SelectedTab | 現在選択されているタブページ |
SelectedIndex | 現在選択されているタブの番号 |
TabPages | TabControlに含まれるタブページのコレクション |
基本的な関係は次のようになります。
C#tabControl1.TabPages.Add(tabPage1);
tabControl1.TabPages.Add(tabPage2);
tabControl1.SelectedTab = tabPage1;
TabControlの中に複数のTabPageがあり、そのうち現在表示されているものがSelectedTabです。
2-2. TabControlをフォームに配置する方法
Visual Studioのデザイナーを使う場合、TabControlは簡単に配置できます。
Windowsフォームを開く
ツールボックスを表示する
「TabControl」をフォームにドラッグ&ドロップする
必要に応じてサイズを変更する
各タブページにコントロールを配置する
コードで配置する場合は、次のように書きます。
C#using System;
using System.Windows.Forms;
public class MainForm : Form
{
private TabControl tabControl;
public MainForm()
{
tabControl = new TabControl();
tabControl.Dock = DockStyle.Fill;
TabPage tabPage1 = new TabPage("基本設定");
TabPage tabPage2 = new TabPage("詳細設定");
tabControl.TabPages.Add(tabPage1);
tabControl.TabPages.Add(tabPage2);
Controls.Add(tabControl);
}
}
Dock = DockStyle.Fillを指定すると、TabControlがフォーム全体に広がります。
2-3. デザイナーでタブを追加・編集する方法
Visual Studioのデザイナーでは、プロパティウィンドウからタブを追加・編集できます。
フォーム上の
TabControlを選択するプロパティウィンドウで
TabPagesを探す...ボタンをクリックするTabPageコレクションエディターで追加・削除・並び替えを行う
各
TabPageのTextプロパティを変更する
Textプロパティは、タブに表示される名前です。たとえばTextを「基本設定」にすると、タブ見出しに「基本設定」と表示されます。
2-4. TabControlの主要プロパティ一覧
TabControlでよく使うプロパティは次の通りです。
| プロパティ | 説明 |
|---|---|
TabPages | タブページの一覧 |
SelectedIndex | 選択中タブのインデックス |
SelectedTab | 選択中のTabPage |
TabCount | タブの数 |
Alignment | タブの表示位置 |
SizeMode | タブサイズの決め方 |
ItemSize | タブのサイズ |
DrawMode | タブ描画方法 |
ImageList | タブに表示する画像リスト |
Multiline | 複数行タブを許可するか |
Appearance | タブの見た目 |
特によく使うのは、TabPages、SelectedIndex、SelectedTabです。タブの追加・削除・切り替えの多くは、この3つを使って実装します。
3. C#でタブを追加・削除する方法
C#のTabControlでは、デザイナーでもコードでもタブを追加できます。固定の画面構成ならデザイナー、実行中に増減するタブならコードで追加するのが一般的です。
3-1. デザイナーでタブを追加する方法
デザイナーでタブを追加する場合は、TabPagesプロパティを使います。
手順は次の通りです。
TabControlを選択するプロパティの
TabPagesを開く「追加」ボタンを押す
追加された
TabPageのTextを変更するタブページ上に必要なコントロールを配置する
デザイナーで追加したタブは、フォームの初期表示時から存在します。そのため、設定画面や固定メニューのように、タブ構成があらかじめ決まっている場合に向いています。
3-2. コードでTabPageを追加する方法
実行中にタブを追加したい場合は、TabPageを作成してTabPages.Addで追加します。
C#TabPage newTab = new TabPage();
newTab.Text = "新しいタブ";
tabControl1.TabPages.Add(newTab);
コンストラクタでタブ名を指定することもできます。
C#TabPage newTab = new TabPage("新しいタブ");
tabControl1.TabPages.Add(newTab);
追加したタブをすぐに選択したい場合は、SelectedTabに設定します。
C#TabPage newTab = new TabPage("新しいタブ");
tabControl1.TabPages.Add(newTab);
tabControl1.SelectedTab = newTab;
タブの中にコントロールを追加することもできます。
C#TabPage newTab = 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);
newTab.Controls.Add(textBox);
newTab.Controls.Add(button);
tabControl1.TabPages.Add(newTab);
tabControl1.SelectedTab = newTab;
3-3. タブ名・表示テキストを変更する方法
タブに表示される名前は、TabPage.Textで変更します。
C#tabPage1.Text = "基本設定";
選択中のタブ名を変更する場合は、次のように書けます。
C#if (tabControl1.SelectedTab != null)
{
tabControl1.SelectedTab.Text = "変更後のタブ名";
}
NameプロパティとTextプロパティは別物です。
| プロパティ | 意味 |
|---|---|
Name | コード上で識別するための名前 |
Text | 画面上に表示する名前 |
たとえば、コードではtabPageSettingsという名前にしておき、画面には「設定」と表示することができます。
C#tabPageSettings.Name = "tabPageSettings";
tabPageSettings.Text = "設定";
3-4. 選択中のタブを削除する方法
選択中のタブを削除するには、SelectedTabを使います。
C#if (tabControl1.SelectedTab != null)
{
tabControl1.TabPages.Remove(tabControl1.SelectedTab);
}
確認メッセージを表示してから削除する場合は、次のようにします。
C#if (tabControl1.SelectedTab != null)
{
DialogResult result = MessageBox.Show(
"選択中のタブを閉じますか?",
"確認",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (result == DialogResult.Yes)
{
tabControl1.TabPages.Remove(tabControl1.SelectedTab);
}
}
削除前に未保存データがあるか確認したい場合は、タブごとに状態を持たせて判定します。
3-5. タブをすべてクリアする方法
すべてのタブを削除するには、TabPages.Clearを使います。
C#tabControl1.TabPages.Clear();
ただし、タブ内に破棄が必要なリソースを持つコントロールがある場合は、単純にClearするだけでなく、必要に応じてDisposeも検討します。
C#foreach (TabPage page in tabControl1.TabPages)
{
page.Dispose();
}
tabControl1.TabPages.Clear();
通常のフォーム部品であればRemoveやClearで十分なことも多いですが、ファイル、画像、データベース接続などを扱う場合はリソース解放を意識しましょう。
4. C#でタブを切り替える方法
C#でタブを切り替えるには、主にSelectedIndexまたはSelectedTabを使います。番号で指定するならSelectedIndex、特定のTabPageを直接指定するならSelectedTabが便利です。
4-1. SelectedIndexでタブを切り替える
SelectedIndexは、選択中タブのインデックス番号を表します。インデックスは0から始まります。
C#tabControl1.SelectedIndex = 0; // 1番目のタブ
tabControl1.SelectedIndex = 1; // 2番目のタブ
tabControl1.SelectedIndex = 2; // 3番目のタブ
存在しないインデックスを指定するとエラーになるため、事前にTabCountを確認すると安全です。
C#int index = 1;
if (index >= 0 && index < tabControl1.TabCount)
{
tabControl1.SelectedIndex = index;
}
次のタブへ移動する処理は次のように書けます。
C#if (tabControl1.SelectedIndex < tabControl1.TabCount - 1)
{
tabControl1.SelectedIndex++;
}
前のタブへ戻る処理は次の通りです。
C#if (tabControl1.SelectedIndex > 0)
{
tabControl1.SelectedIndex--;
}
4-2. SelectedTabで特定のタブを選択する
SelectedTabを使うと、TabPageオブジェクトを直接指定してタブを切り替えられます。
C#tabControl1.SelectedTab = tabPageSettings;
タブ名や条件から対象のタブを探して切り替えることもできます。
C#foreach (TabPage page in tabControl1.TabPages)
{
if (page.Text == "設定")
{
tabControl1.SelectedTab = page;
break;
}
}
SelectedIndexは順番に依存しますが、SelectedTabは対象のタブを直接指定できます。タブの並び順が変わる可能性がある場合は、SelectedTabのほうが安全です。
4-3. ボタンクリックでタブを切り替える実装例
「次へ」「戻る」ボタンでタブを切り替える実装例です。
C#private void buttonNext_Click(object sender, EventArgs e)
{
if (tabControl1.SelectedIndex < tabControl1.TabCount - 1)
{
tabControl1.SelectedIndex++;
}
}
private void buttonBack_Click(object sender, EventArgs e)
{
if (tabControl1.SelectedIndex > 0)
{
tabControl1.SelectedIndex--;
}
}
ウィザード形式の入力画面では、タブ見出しをユーザーに操作させず、ボタンで画面遷移させる設計もあります。
特定のタブへ移動するボタンなら、次のように書きます。
C#private void buttonSettings_Click(object sender, EventArgs e)
{
tabControl1.SelectedTab = tabPageSettings;
}
4-4. タブ切り替え時のイベント処理
タブが切り替わったタイミングで処理を行いたい場合は、SelectedIndexChangedイベントを使います。
C#private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
TabPage selectedPage = tabControl1.SelectedTab;
if (selectedPage != null)
{
labelStatus.Text = selectedPage.Text + "を表示中";
}
}
タブ変更前に処理したい場合はSelecting、変更後に処理したい場合はSelectedやSelectedIndexChangedを使います。
C#private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
// タブが選択される前の処理
}
private void tabControl1_Selected(object sender, TabControlEventArgs e)
{
// タブが選択された後の処理
}
4-5. タブ切り替えをキャンセルする方法
入力チェックに失敗した場合など、タブの切り替えを止めたいときはSelectingイベントでe.Cancel = trueを設定します。
C#private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (tabControl1.SelectedTab == tabPageInput)
{
if (string.IsNullOrWhiteSpace(textBoxName.Text))
{
MessageBox.Show("名前を入力してください。");
e.Cancel = true;
}
}
}
この例では、入力タブから別のタブに移動しようとしたとき、名前が未入力なら切り替えをキャンセルします。
5. TabControlのイベント活用
TabControlを実用的に使うには、イベント処理が重要です。タブが変わったタイミングで画面を更新したり、入力チェックを行ったり、タブごとに処理を分岐したりできます。
5-1. SelectedIndexChangedイベントの使い方
SelectedIndexChangedは、選択中のタブが変わったときに発生します。
C#private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
int index = tabControl1.SelectedIndex;
string tabName = tabControl1.SelectedTab?.Text ?? "";
labelStatus.Text = $"現在のタブ: {tabName} ({index})";
}
画面下部にステータスを表示したり、タブに応じてボタンの有効・無効を切り替えたりする場面でよく使います。
C#private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
buttonBack.Enabled = tabControl1.SelectedIndex > 0;
buttonNext.Enabled = tabControl1.SelectedIndex < tabControl1.TabCount - 1;
}
5-2. SelectingイベントとSelectedイベントの違い
TabControlには、似た名前のイベントがいくつかあります。
| イベント | 発生タイミング | キャンセル |
|---|---|---|
Selecting | タブが選択される前 | 可能 |
Selected | タブが選択された後 | 不可 |
Deselecting | 現在のタブが解除される前 | 可能 |
Deselected | 現在のタブが解除された後 | 不可 |
SelectedIndexChanged | 選択インデックスが変わった後 | 不可 |
入力チェックなど「切り替えを止めたい」場合はSelectingまたはDeselectingを使います。切り替え後に表示内容を更新したい場合はSelectedやSelectedIndexChangedが向いています。
5-3. タブ変更時に入力チェックを行う方法
タブ変更時に入力チェックを行う例です。
C#private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (tabControl1.SelectedTab == tabPageUserInfo)
{
if (string.IsNullOrWhiteSpace(textBoxUserName.Text))
{
MessageBox.Show("ユーザー名を入力してください。");
e.Cancel = true;
return;
}
if (string.IsNullOrWhiteSpace(textBoxEmail.Text))
{
MessageBox.Show("メールアドレスを入力してください。");
e.Cancel = true;
return;
}
}
}
ポイントは、現在表示中のタブから移動しようとしているタイミングで入力内容を確認することです。
また、移動先のタブを判定したい場合はe.TabPageを使います。
C#private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
if (e.TabPage == tabPageConfirm)
{
if (!ValidateInput())
{
MessageBox.Show("入力内容に不備があります。");
e.Cancel = true;
}
}
}
private bool ValidateInput()
{
return !string.IsNullOrWhiteSpace(textBoxUserName.Text);
}
5-4. タブごとに処理を分岐する方法
タブごとに処理を変える場合は、SelectedTabやSelectedIndexを使って分岐します。
C#private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
if (tabControl1.SelectedTab == tabPageSearch)
{
LoadSearchConditions();
}
else if (tabControl1.SelectedTab == tabPageResult)
{
LoadSearchResults();
}
else if (tabControl1.SelectedTab == tabPageDetail)
{
LoadDetail();
}
}
SelectedIndexで分岐することもできます。
C#switch (tabControl1.SelectedIndex)
{
case 0:
LoadBasicSettings();
break;
case 1:
LoadDisplaySettings();
break;
case 2:
LoadAdvancedSettings();
break;
}
ただし、タブの順番が変わるとSelectedIndexの意味も変わります。保守性を重視するなら、SelectedTabで比較する方法がおすすめです。
5-5. タブ切り替え時によくあるエラー
タブ切り替え時によくあるエラーには、次のようなものがあります。
| エラー・現象 | 原因 | 対策 |
|---|---|---|
ArgumentOutOfRangeException | 存在しないSelectedIndexを指定した | TabCountを確認する |
NullReferenceException | SelectedTabがnullなのに参照した | nullチェックを行う |
| イベントが何度も発生する | イベント内でさらにタブを変更している | 再入防止フラグを使う |
| 入力チェック後に移動してしまう | e.Cancel = trueを設定していない | Selectingでキャンセルする |
| 意図しないタブが選ばれる | タブの追加・削除でインデックスが変わった | SelectedTabで指定する |
再入防止フラグの例は次の通りです。
C#private bool _changingTab = false;
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
if (_changingTab)
{
return;
}
try
{
_changingTab = true;
// タブ変更時の処理
}
finally
{
_changingTab = false;
}
}
6. TabControlのデザインを変更する方法
TabControlは標準のままでも使えますが、業務アプリや独自UIではデザインを変更したいことがあります。サイズ、位置、色、アイコン、閉じるボタンなどを調整できます。
6-1. タブのサイズ・位置を変更する
タブの位置はAlignmentプロパティで変更できます。
C#tabControl1.Alignment = TabAlignment.Top; // 上
tabControl1.Alignment = TabAlignment.Bottom; // 下
tabControl1.Alignment = TabAlignment.Left; // 左
tabControl1.Alignment = TabAlignment.Right; // 右
タブのサイズを固定したい場合は、SizeModeとItemSizeを使います。
C#tabControl1.SizeMode = TabSizeMode.Fixed;
tabControl1.ItemSize = new Size(120, 30);
複数行タブを許可する場合は、Multilineをtrueにします。
C#tabControl1.Multiline = true;
タブ数が多い画面では、複数行にするよりも、タブ数自体を見直すほうがよい場合もあります。
6-2. タブの文字色・背景色を変更する
WinFormsのTabControlでは、標準プロパティだけでタブ見出しの色を自由に変更するのは難しい場合があります。タブの文字色や背景色を細かく変更したい場合は、オーナードローを使います。
まず、DrawModeをOwnerDrawFixedに設定します。
C#tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
tabControl1.DrawItem += tabControl1_DrawItem;
次に、DrawItemイベントで描画します。
C#private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
TabControl tabControl = (TabControl)sender;
TabPage page = tabControl.TabPages[e.Index];
Rectangle rect = tabControl.GetTabRect(e.Index);
bool selected = (e.Index == tabControl.SelectedIndex);
Color backColor = selected ? Color.White : Color.LightGray;
Color textColor = selected ? Color.Black : Color.DarkGray;
using (SolidBrush backBrush = new SolidBrush(backColor))
using (SolidBrush textBrush = new SolidBrush(textColor))
{
e.Graphics.FillRectangle(backBrush, rect);
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
e.Graphics.DrawString(page.Text, tabControl.Font, textBrush, rect, format);
}
}
このようにすると、選択中タブと未選択タブで色を変えられます。
6-3. DrawModeを使ってタブをカスタマイズする
DrawModeを使うと、タブの見た目を自分で描画できます。たとえば、選択中のタブだけ太字にすることもできます。
C#private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
TabControl tabControl = (TabControl)sender;
TabPage page = tabControl.TabPages[e.Index];
Rectangle rect = tabControl.GetTabRect(e.Index);
bool selected = e.Index == tabControl.SelectedIndex;
using (Font font = new Font(
tabControl.Font,
selected ? FontStyle.Bold : FontStyle.Regular))
using (Brush brush = new SolidBrush(Color.Black))
{
StringFormat format = new StringFormat
{
Alignment = StringAlignment.Center,
LineAlignment = StringAlignment.Center
};
e.Graphics.DrawString(page.Text, font, brush, rect, format);
}
}
ただし、オーナードローは標準の見た目を自分で描く必要があるため、やりすぎるとコードが複雑になります。単純なデザイン変更にとどめるか、必要に応じてカスタムコントロール化しましょう。
6-4. アイコン付きタブを作る方法
タブにアイコンを表示するには、ImageListを使います。
C#ImageList imageList = new ImageList();
imageList.Images.Add("home", Image.FromFile("home.png"));
imageList.Images.Add("settings", Image.FromFile("settings.png"));
tabControl1.ImageList = imageList;
tabPageHome.ImageKey = "home";
tabPageSettings.ImageKey = "settings";
または、インデックスで指定できます。
C#tabPageHome.ImageIndex = 0;
tabPageSettings.ImageIndex = 1;
アイコン付きタブは、設定画面や管理画面で視認性を高めたいときに便利です。ただし、アイコンだけに頼ると意味が伝わりにくいため、基本的にはテキストと併用するのがおすすめです。
6-5. 閉じるボタン付きタブを作る方法
WinFormsの標準TabControlには、タブごとの閉じるボタンはありません。そのため、DrawItemで「×」を描画し、MouseDownでクリック位置を判定する方法がよく使われます。
まず、閉じるボタンの位置を描画します。
C#private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
{
TabControl tabControl = (TabControl)sender;
TabPage page = tabControl.TabPages[e.Index];
Rectangle tabRect = tabControl.GetTabRect(e.Index);
Rectangle closeRect = new Rectangle(
tabRect.Right - 20,
tabRect.Top + 6,
12,
12);
e.Graphics.DrawString(page.Text, tabControl.Font, Brushes.Black, tabRect.Left + 6, tabRect.Top + 6);
e.Graphics.DrawString("×", tabControl.Font, Brushes.Black, closeRect);
}
次に、クリック位置を判定してタブを閉じます。
C#private void tabControl1_MouseDown(object sender, MouseEventArgs e)
{
for (int i = 0; i < tabControl1.TabPages.Count; i++)
{
Rectangle tabRect = tabControl1.GetTabRect(i);
Rectangle closeRect = new Rectangle(
tabRect.Right - 20,
tabRect.Top + 6,
12,
12);
if (closeRect.Contains(e.Location))
{
tabControl1.TabPages.RemoveAt(i);
break;
}
}
}
実際のアプリでは、未保存のデータがある場合に確認ダイアログを表示するなどの処理も追加するとよいでしょう。
7. 実用的なTabControlの実装パターン
TabControlは、単にページを切り替えるだけでなく、動的な画面生成やUserControlとの組み合わせによって、より保守しやすいUIを作れます。
7-1. 動的にタブを増やす画面の作り方
動的にタブを増やす代表例は、検索結果やドキュメントをタブで開く画面です。
C#private void AddDocumentTab(string title, string content)
{
TabPage tabPage = new TabPage(title);
TextBox textBox = new TextBox();
textBox.Multiline = true;
textBox.Dock = DockStyle.Fill;
textBox.Text = content;
tabPage.Controls.Add(textBox);
tabControl1.TabPages.Add(tabPage);
tabControl1.SelectedTab = tabPage;
}
呼び出し例です。
C#AddDocumentTab("メモ1", "これはメモ1の内容です。");
AddDocumentTab("メモ2", "これはメモ2の内容です。");
同じ名前のタブを重複して開かないようにする場合は、既存タブを検索します。
C#private void OpenOrSelectTab(string title)
{
foreach (TabPage page in tabControl1.TabPages)
{
if (page.Text == title)
{
tabControl1.SelectedTab = page;
return;
}
}
TabPage newPage = new TabPage(title);
tabControl1.TabPages.Add(newPage);
tabControl1.SelectedTab = newPage;
}
7-2. タブごとに異なるUserControlを表示する方法
複雑な画面では、タブページに直接大量のコントロールを置くよりも、UserControlを使って画面を分割すると保守しやすくなります。
C#private void AddUserControlTab(string title, UserControl control)
{
TabPage tabPage = new TabPage(title);
control.Dock = DockStyle.Fill;
tabPage.Controls.Add(control);
tabControl1.TabPages.Add(tabPage);
}
呼び出し例です。
C#AddUserControlTab("ユーザー管理", new UserManagementControl());
AddUserControlTab("商品管理", new ProductManagementControl());
AddUserControlTab("ログ管理", new LogViewerControl());
このようにすれば、各タブの処理をそれぞれのUserControlに分離できます。
7-3. 設定画面をタブで整理する方法
設定画面は、TabControlと相性がよい画面の1つです。
たとえば、次のようにタブを分けます。
| タブ | 内容 |
|---|---|
| 基本設定 | ユーザー名、言語、テーマ |
| 表示設定 | フォント、画面サイズ、配色 |
| 通知設定 | メール通知、通知音 |
| 詳細設定 | ログ、キャッシュ、保存先 |
設定画面の実装例です。
C#private void LoadSettings()
{
textBoxUserName.Text = Properties.Settings.Default.UserName;
checkBoxNotification.Checked = Properties.Settings.Default.EnableNotification;
}
private void SaveSettings()
{
Properties.Settings.Default.UserName = textBoxUserName.Text;
Properties.Settings.Default.EnableNotification = checkBoxNotification.Checked;
Properties.Settings.Default.Save();
}
保存ボタンでは、現在のタブだけでなく全タブの入力値をまとめて保存する設計にすると分かりやすくなります。
C#private void buttonSave_Click(object sender, EventArgs e)
{
SaveSettings();
MessageBox.Show("設定を保存しました。");
}
7-4. ブラウザ風のタブUIを作る方法
ブラウザ風のタブUIでは、次のような機能が必要になります。
| 機能 | 内容 |
|---|---|
| 新しいタブ | ボタンやメニューからタブを追加する |
| タブを閉じる | タブ上の×ボタンで削除する |
| 選択タブの管理 | 新規タブを追加後、自動で選択する |
| 未保存チェック | 閉じる前に確認する |
| タブタイトル更新 | 表示中の内容に応じてタブ名を変える |
簡単なブラウザ風タブの追加例です。
C#private int _tabNumber = 1;
private void AddBrowserTab()
{
TabPage tabPage = new TabPage($"新しいタブ {_tabNumber}");
TextBox addressBar = new TextBox();
addressBar.Dock = DockStyle.Top;
WebBrowser browser = new WebBrowser();
browser.Dock = DockStyle.Fill;
tabPage.Controls.Add(browser);
tabPage.Controls.Add(addressBar);
tabControl1.TabPages.Add(tabPage);
tabControl1.SelectedTab = tabPage;
_tabNumber++;
}
現在ではWebBrowserコントロールの代わりに、用途に応じてWebView2を使うこともあります。ブラウザ風UIを本格的に作る場合は、タブ管理、履歴、読み込み状態、エラー処理なども設計しましょう。
7-5. タブの状態を保存・復元する方法
アプリ終了時に開いていたタブを、次回起動時に復元したい場合があります。基本的には、タブの情報をリストとして保存しておき、起動時に再作成します。
保存対象の例です。
| 保存する情報 | 例 |
|---|---|
| タブ名 | 「顧客A」「設定」 |
| 表示内容のID | 顧客ID、ファイルパス |
| 選択中タブ | SelectedIndex |
| 入力内容 | テキストボックスの値 |
簡単な復元イメージは次の通りです。
C#private void RestoreTabs(List<string> tabNames, int selectedIndex)
{
tabControl1.TabPages.Clear();
foreach (string name in tabNames)
{
TabPage page = new TabPage(name);
tabControl1.TabPages.Add(page);
}
if (selectedIndex >= 0 && selectedIndex < tabControl1.TabCount)
{
tabControl1.SelectedIndex = selectedIndex;
}
}
実際には、JSONファイルやアプリ設定に保存することが多いです。
8. WPFでタブを使う場合の基本
C#でタブUIを作る場合、WinFormsだけでなくWPFでもTabControlを使えます。ただし、WinFormsとは構造や考え方が少し異なります。
8-1. WPFのTabControlとTabItemの基本
WPFでは、TabControlの中にTabItemを配置します。
| WinForms | WPF |
|---|---|
TabControl | TabControl |
TabPage | TabItem |
Text | Header |
Controls | Content |
WinFormsではTabPage.Textでタブ名を設定しますが、WPFではTabItem.Headerを使います。
8-2. XAMLでタブを定義する方法
WPFでは、XAMLでタブを定義するのが一般的です。
XML<TabControl>
<TabItem Header="基本設定">
<StackPanel Margin="10">
<TextBlock Text="ユーザー名" />
<TextBox Width="200" />
</StackPanel>
</TabItem>
<TabItem Header="詳細設定">
<StackPanel Margin="10">
<CheckBox Content="ログを出力する" />
<CheckBox Content="通知を有効にする" />
</StackPanel>
</TabItem>
</TabControl>
WPFでは、レイアウトやスタイルをXAMLで柔軟に定義できます。見た目を細かくカスタマイズしたい場合は、WinFormsよりWPFのほうが向いていることがあります。
8-3. C#コードからタブを追加する方法
WPFでも、C#コードからタブを追加できます。
C#TabItem tabItem = new TabItem();
tabItem.Header = "新しいタブ";
TextBox textBox = new TextBox();
textBox.Text = "タブの内容です。";
tabItem.Content = textBox;
tabControl1.Items.Add(tabItem);
tabControl1.SelectedItem = tabItem;
複数のコントロールを入れたい場合は、GridやStackPanelなどのレイアウトコンテナをContentに設定します。
C#StackPanel panel = new StackPanel();
panel.Margin = new Thickness(10);
panel.Children.Add(new TextBlock { Text = "名前" });
panel.Children.Add(new TextBox { Width = 200 });
TabItem tabItem = new TabItem
{
Header = "入力",
Content = panel
};
tabControl1.Items.Add(tabItem);
8-4. WinFormsのTabControlとの違い
WinFormsとWPFのTabControlには、次のような違いがあります。
| 項目 | WinForms | WPF |
|---|---|---|
| 画面定義 | デザイナー中心 | XAML中心 |
| タブページ | TabPage | TabItem |
| タブ名 | Text | Header |
| 中身 | Controls.Add | Contentまたはテンプレート |
| デザイン変更 | オーナードローが必要なことが多い | StyleやTemplateで柔軟 |
| データバインディング | 限定的 | 得意 |
| MVVM | あまり使わない | よく使う |
簡単な業務ツールならWinFormsでも十分です。デザイン性、拡張性、データバインディングを重視するならWPFが向いています。
8-5. MVVMでTabControlを扱う考え方
WPFでMVVMを使う場合、タブをViewModelのコレクションとして扱うことが多いです。
たとえば、タブ用のViewModelを用意します。
C#public class TabViewModel
{
public string Header { get; set; }
public object Content { get; set; }
}
メインViewModelでタブ一覧を持ちます。
C#public ObservableCollection<TabViewModel> Tabs { get; } = new ObservableCollection<TabViewModel>();
public TabViewModel SelectedTab { get; set; }
XAMLではItemsSourceにバインドします。
XML<TabControl ItemsSource="{Binding Tabs}"
SelectedItem="{Binding SelectedTab}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
MVVMでは、画面部品を直接操作するのではなく、データの変化によってタブを追加・削除・選択する考え方になります。
9. C#のタブ文字「\t」とTabControlの違い
C#で「タブ」と検索すると、UIのTabControlだけでなく、文字列のタブ文字\tに関する情報も出てきます。両者はまったく別のものです。
9-1. タブ文字とは何か
タブ文字とは、文字列の中で一定の間隔を空けるための制御文字です。C#では\tと書きます。
C#string text = "名前\t年齢\t住所";
\tは、主にコンソール出力やテキストデータで列をそろえるために使われます。
C#Console.WriteLine("名前\t年齢\t住所");
Console.WriteLine("田中\t30\t東京");
Console.WriteLine("佐藤\t25\t大阪");
出力イメージは次のようになります。
名前 年齢 住所
田中 30 東京
佐藤 25 大阪
9-2. 文字列にタブを入れる方法
C#で文字列にタブを入れるには、エスケープシーケンス\tを使います。
C#string message = "A\tB\tC";
文字列補間でも使えます。
C#string name = "田中";
int age = 30;
string line = $"{name}\t{age}";
逐語的文字列リテラルでは注意が必要です。
C#string normal = "A\tB"; // タブとして扱われる
string verbatim = @"A\tB"; // \ と t の2文字として扱われる
@"A\tB"のように@を付けると、\tはタブ文字ではなく、そのままバックスラッシュとtとして扱われます。
9-3. TextBoxやConsoleでタブを表示する方法
Consoleでは、\tを使ってタブ文字を出力できます。
C#Console.WriteLine("商品名\t価格\t在庫");
Console.WriteLine("りんご\t120\tあり");
Console.WriteLine("みかん\t80\tなし");
TextBoxに表示する場合も、文字列として\tを入れられます。
C#textBox1.Text = "名前\t年齢\t住所";
ただし、TextBoxでタブを見やすく表示できるかは、フォントや設定によって変わります。列をきれいにそろえたい場合は、ListView、DataGridView、WPFのDataGridなどを使うほうが適しています。
9-4. UIのタブと文字列のタブを混同しないポイント
UIのタブと文字列のタブは、用途がまったく違います。
| 種類 | C#での表現 | 用途 |
|---|---|---|
| UIのタブ | TabControl、TabPage | 画面を切り替える |
| 文字列のタブ | "\t" | 文字列内で間隔を空ける |
たとえば、画面に「基本設定」「詳細設定」のような切り替えタブを作りたいならTabControlを使います。一方、文字列の中で「名前」「年齢」「住所」を区切りたいなら\tを使います。
10. TabControlでよくあるトラブルと解決策
TabControlは便利ですが、実装中によくあるトラブルもあります。原因と対策を知っておくと、エラー対応がスムーズになります。
10-1. タブが表示されない場合の原因
タブが表示されない場合は、次の点を確認しましょう。
| 原因 | 対策 |
|---|---|
TabControlがフォームに追加されていない | Controls.Addを確認する |
| サイズが小さすぎる | SizeやDockを確認する |
Visibleがfalseになっている | Visible = trueにする |
TabPagesが空 | タブを追加する |
| 他のコントロールに隠れている | 前面・背面の順序を確認する |
コードで配置する場合は、フォームに追加しているか確認します。
C#Controls.Add(tabControl1);
また、サイズを指定していないと見えない場合があります。
C#tabControl1.Dock = DockStyle.Fill;
10-2. タブ切り替えイベントが発火しない場合
イベントが発火しない場合は、イベントハンドラーが正しく関連付けられているか確認します。
C#tabControl1.SelectedIndexChanged += tabControl1_SelectedIndexChanged;
デザイナーで設定した場合でも、イベントが消えていないかプロパティウィンドウのイベント一覧を確認しましょう。
また、同じタブを再選択してもSelectedIndexChangedは発生しません。選択インデックスが変わったときだけ発生します。
10-3. タブの色が変更できない場合
TabPage.BackColorを変更しても、タブ見出しの色が変わらない場合があります。
C#tabPage1.BackColor = Color.LightYellow;
これはタブページの中身の背景色であり、タブ見出しそのものの背景色ではありません。タブ見出しの色を変更したい場合は、DrawModeをOwnerDrawFixedにして、DrawItemイベントで描画します。
C#tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
tabControl1.DrawItem += tabControl1_DrawItem;
タブの見出しとタブページの背景は別物として考えましょう。
10-4. 動的に追加したタブの中身が表示されない場合
動的に追加したタブの中身が表示されない場合は、次の点を確認してください。
| 原因 | 対策 |
|---|---|
コントロールをTabPageに追加していない | tabPage.Controls.Addを使う |
| サイズや位置が不適切 | DockやLocationを設定する |
Visibleがfalse | Visibleを確認する |
| 親コントロールを間違えている | TabPageに追加する |
| 追加後に選択していない | SelectedTabを設定する |
よくある間違いは、TabControlに直接コントロールを追加してしまうことです。
C#// 非推奨:TabControlに直接追加している
tabControl1.Controls.Add(textBox1);
タブ内に表示したい場合は、TabPageに追加します。
C#TabPage page = new TabPage("入力");
TextBox textBox = new TextBox();
textBox.Dock = DockStyle.Fill;
page.Controls.Add(textBox);
tabControl1.TabPages.Add(page);
tabControl1.SelectedTab = page;
10-5. SelectedIndexの指定でエラーになる場合
SelectedIndexで存在しないインデックスを指定すると、エラーになります。
C#tabControl1.SelectedIndex = 5;
タブが3つしかない場合、指定できるインデックスは0、1、2です。安全に切り替えるには、範囲チェックを行います。
C#private void SelectTabSafe(int index)
{
if (index >= 0 && index < tabControl1.TabCount)
{
tabControl1.SelectedIndex = index;
}
}
タブが1つもない場合、SelectedIndexは-1になることがあります。削除処理や初期化処理では、タブ数を確認してから操作しましょう。
C#if (tabControl1.TabCount > 0)
{
tabControl1.SelectedIndex = 0;
}
11. TabControlを使うときの設計ポイント
TabControlは便利ですが、使い方を間違えると画面が複雑になります。ここでは、保守しやすく使いやすいタブUIにするための設計ポイントを紹介します。
11-1. タブを増やしすぎない
タブが多すぎると、ユーザーは目的の画面を探しにくくなります。目安として、固定タブは3〜7個程度に収めると見やすくなります。
タブが多くなる場合は、次のような見直しを検討しましょう。
| 問題 | 改善案 |
|---|---|
| タブが多すぎる | カテゴリを再整理する |
| タブ名が長い | 短い名称にする |
| 似たタブがある | 1つに統合する |
| 階層が深い | メニューやナビゲーションに分ける |
タブは「同じ階層の情報を切り替える」ためのUIです。階層構造が深い情報には、ツリービューやサイドメニューのほうが向いている場合があります。
11-2. タブ名は短く分かりやすくする
タブ名は、短く直感的に分かる名前にしましょう。
| 良い例 | 悪い例 |
|---|---|
| 基本設定 | ユーザーが最初に設定する基本的な情報 |
| 通知 | メールおよびシステム通知に関する設定 |
| 履歴 | 過去に実行された処理の一覧 |
| 詳細 | 高度なオプション設定項目 |
長いタブ名は画面を圧迫します。必要であれば、タブ内の見出しや説明文で補足するとよいでしょう。
11-3. 処理をタブごとに分離する
すべての処理をフォームに直接書くと、コードが長くなり保守しにくくなります。タブごとに処理を分けることで、見通しがよくなります。
たとえば、次のように処理を分割します。
C#private void LoadBasicTab()
{
// 基本設定タブの読み込み
}
private void LoadNotificationTab()
{
// 通知設定タブの読み込み
}
private void LoadAdvancedTab()
{
// 詳細設定タブの読み込み
}
さらに規模が大きい場合は、UserControlを使って画面単位で分けるのがおすすめです。
11-4. UserControlを活用して保守性を高める
タブごとの内容が複雑な場合は、各タブをUserControlとして作成しましょう。
C#UserControl basicControl = new BasicSettingsControl();
basicControl.Dock = DockStyle.Fill;
tabPageBasic.Controls.Add(basicControl);
UserControlを使うメリットは次の通りです。
| メリット | 内容 |
|---|---|
| コードが分かれる | フォームが肥大化しにくい |
| 再利用できる | 別画面でも同じ部品を使える |
| テストしやすい | 機能単位で確認できる |
| 担当を分けやすい | 複数人開発に向いている |
タブ画面が大きくなるほど、UserControlによる分割の効果は大きくなります。
11-5. タブUIが向いている画面・向いていない画面
タブUIには向き不向きがあります。
タブUIが向いている画面は次の通りです。
| 向いている画面 | 理由 |
|---|---|
| 設定画面 | 関連項目をカテゴリ分けしやすい |
| 詳細情報画面 | 基本情報、履歴、メモなどを分けやすい |
| 管理画面 | 機能ごとに画面を整理しやすい |
| 複数ドキュメント画面 | 開いている内容を切り替えやすい |
一方で、次のような画面には向かない場合があります。
| 向いていない画面 | 理由 |
|---|---|
| 手順が決まっている入力画面 | ウィザード形式のほうが分かりやすい |
| 階層が深い画面 | サイドメニューやツリーのほうが向いている |
| タブ数が非常に多い画面 | 探しにくくなる |
| 頻繁に比較する画面 | 並べて表示したほうがよい |
タブは便利ですが、何でもタブにすればよいわけではありません。ユーザーが迷わず操作できるかを基準に設計しましょう。
12. C#のタブに関するよくある質問
最後に、C#のタブやTabControlに関するよくある質問をまとめます。
12-1. C#でタブを追加するには?
WinFormsでは、TabPageを作成してTabControl.TabPages.Addで追加します。
C#TabPage page = new TabPage("新しいタブ");
tabControl1.TabPages.Add(page);
追加したタブをすぐ表示したい場合は、SelectedTabに設定します。
C#tabControl1.SelectedTab = page;
12-2. C#でタブを切り替えるには?
タブを切り替えるには、SelectedIndexまたはSelectedTabを使います。
C#tabControl1.SelectedIndex = 0;
または、特定のTabPageを指定します。
C#tabControl1.SelectedTab = tabPageSettings;
番号で切り替えるならSelectedIndex、対象のタブが決まっているならSelectedTabが便利です。
12-3. TabControlのタブ名を変更するには?
タブ名はTabPage.Textで変更します。
C#tabPage1.Text = "変更後の名前";
選択中タブの名前を変更する場合は、次のように書きます。
C#if (tabControl1.SelectedTab != null)
{
tabControl1.SelectedTab.Text = "新しい名前";
}
12-4. タブに閉じるボタンを付けるには?
WinFormsの標準TabControlには、タブごとの閉じるボタンは用意されていません。実装する場合は、DrawModeをOwnerDrawFixedにして「×」を描画し、MouseDownイベントでクリック位置を判定します。
C#tabControl1.DrawMode = TabDrawMode.OwnerDrawFixed;
tabControl1.DrawItem += tabControl1_DrawItem;
tabControl1.MouseDown += tabControl1_MouseDown;
本格的なタブUIを作る場合は、未保存チェックやタブ削除後の選択位置も考慮しましょう。
12-5. WinFormsとWPFのTabControlはどちらを使うべき?
既存のWinFormsアプリにタブを追加するなら、WinFormsのTabControlを使うのが自然です。新規開発で、デザインの自由度やデータバインディング、MVVMを重視するならWPFが向いています。
| 判断基準 | おすすめ |
|---|---|
| 既存アプリがWinForms | WinForms |
| シンプルな業務ツール | WinForms |
| デザインを細かく作り込みたい | WPF |
| MVVMで開発したい | WPF |
| データバインディングを多用したい | WPF |
どちらが絶対に優れているというより、アプリの目的や既存資産に合わせて選ぶことが大切です。
12-6. C#でタブ文字を入力するには?
文字列にタブ文字を入れるには、\tを使います。
C#string text = "名前\t年齢\t住所";
Consoleに出力する例です。
C#Console.WriteLine("名前\t年齢\t住所");
Console.WriteLine("田中\t30\t東京");
ただし、これはUIのタブではなく、文字列内の制御文字です。画面をタブで切り替えたい場合はTabControlを使います。
まとめ
C#でタブを扱う場合、画面UIとしてのタブは主にTabControlを使って実装します。WinFormsではTabControlの中にTabPageを追加し、SelectedIndexやSelectedTabでタブを切り替えます。
タブの追加はTabPages.Add、削除はTabPages.RemoveやRemoveAt、すべて削除する場合はClearを使います。タブ切り替え時の処理にはSelectedIndexChanged、切り替え前の入力チェックやキャンセルにはSelectingイベントが便利です。
また、タブの色や見た目を変更したい場合は、DrawModeを使ったオーナードローが必要になることがあります。アイコン付きタブや閉じるボタン付きタブも実装できますが、コードが複雑になりやすいため、保守性を意識して設計することが大切です。
WPFではTabControlとTabItemを使い、XAMLやデータバインディングによって柔軟なタブUIを作成できます。WinFormsとWPFではプロパティや設計思想が異なるため、アプリの種類に合わせて使い分けましょう。
さらに、C#の「タブ」には文字列のタブ文字\tという意味もあります。画面を切り替えるタブはTabControl、文字列内の間隔を空けるタブは\tと覚えておくと混同しにくくなります。
TabControlは、設定画面、管理画面、入力画面、ブラウザ風UIなど、さまざまな場面で活用できます。タブを増やしすぎず、タブ名を分かりやすくし、必要に応じてUserControlで処理を分離することで、使いやすく保守しやすいC#アプリを作ることができます。

